cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jbel...@apache.org
Subject svn commit: r935088 - in /cassandra/trunk: interface/ interface/thrift/gen-java/org/apache/cassandra/thrift/ src/java/org/apache/cassandra/cli/ src/java/org/apache/cassandra/db/ src/java/org/apache/cassandra/thrift/ src/java/org/apache/cassandra/utils/...
Date Fri, 16 Apr 2010 22:04:47 GMT
Author: jbellis
Date: Fri Apr 16 22:04:46 2010
New Revision: 935088

URL: http://svn.apache.org/viewvc?rev=935088&view=rev
Log:
Add ExpiringColumn and Column ttl.
patch by Sylvain Lebresne; reviewed by jbellis for CASSANDRA-699

Added:
    cassandra/trunk/src/java/org/apache/cassandra/db/ExpiringColumn.java
Modified:
    cassandra/trunk/interface/cassandra.thrift
    cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java
    cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java
    cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java
    cassandra/trunk/src/java/org/apache/cassandra/db/Column.java
    cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java
    cassandra/trunk/src/java/org/apache/cassandra/db/ColumnSerializer.java
    cassandra/trunk/src/java/org/apache/cassandra/db/RowMutation.java
    cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java
    cassandra/trunk/src/java/org/apache/cassandra/thrift/ThriftValidation.java
    cassandra/trunk/src/java/org/apache/cassandra/utils/FBUtilities.java
    cassandra/trunk/test/system/test_thrift_server.py
    cassandra/trunk/test/unit/org/apache/cassandra/client/TestRingCache.java
    cassandra/trunk/test/unit/org/apache/cassandra/service/EmbeddedCassandraServiceTest.java

Modified: cassandra/trunk/interface/cassandra.thrift
URL: http://svn.apache.org/viewvc/cassandra/trunk/interface/cassandra.thrift?rev=935088&r1=935087&r2=935088&view=diff
==============================================================================
--- cassandra/trunk/interface/cassandra.thrift (original)
+++ cassandra/trunk/interface/cassandra.thrift Fri Apr 16 22:04:46 2010
@@ -57,11 +57,15 @@ const string VERSION = "4.0.0"
  *        is used as a key to its value.
  * @param value. Some data
  * @param timestamp. Used to record when data was sent to be written.
+ * @param ttl. A delay (in seconds) after which the column will be automatically deleted. If this parameter is not
+ *             provided or is <= 0, the column will never be deleted automatically (and will have no ttl when queried).
+ *             Note that, if set, the column will be deleted from a node ttl seconds after the column reach the node.
  */
 struct Column {
    1: required binary name,
    2: required binary value,
    3: required i64 timestamp,
+   4: optional i32 ttl,
 }
 
 /** A named list of columns.
@@ -407,16 +411,13 @@ service Cassandra {
   # modification methods
 
   /**
-    Insert a Column consisting of (column_path.column, value, timestamp) at the given column_path.column_family and optional
-    column_path.super_column. Note that column_path.column is here required, since a SuperColumn cannot directly contain binary
-    values -- it can only contain sub-Columns. 
+   * Insert a Column at the given column_parent.column_family and optional column_parent.super_column.
    */
   void insert(1:required string keyspace, 
               2:required binary key, 
-              3:required ColumnPath column_path, 
-              4:required binary value, 
-              5:required i64 timestamp, 
-              6:required ConsistencyLevel consistency_level=ONE)
+              3:required ColumnParent column_parent,
+              4:required Column column,
+              5:required ConsistencyLevel consistency_level=ONE)
        throws (1:InvalidRequestException ire, 2:UnavailableException ue, 3:TimedOutException te),
 
   /**

Modified: cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java?rev=935088&r1=935087&r2=935088&view=diff
==============================================================================
--- cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java (original)
+++ cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/Cassandra.java Fri Apr 16 22:04:46 2010
@@ -133,18 +133,15 @@ public class Cassandra {
     public List<KeySlice> get_range_slices(String keyspace, ColumnParent column_parent, SlicePredicate predicate, KeyRange range, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException;
 
     /**
-     * Insert a Column consisting of (column_path.column, value, timestamp) at the given column_path.column_family and optional
-     * column_path.super_column. Note that column_path.column is here required, since a SuperColumn cannot directly contain binary
-     * values -- it can only contain sub-Columns.
+     * Insert a Column at the given column_parent.column_family and optional column_parent.super_column.
      * 
      * @param keyspace
      * @param key
-     * @param column_path
-     * @param value
-     * @param timestamp
+     * @param column_parent
+     * @param column
      * @param consistency_level
      */
-    public void insert(String keyspace, byte[] key, ColumnPath column_path, byte[] value, long timestamp, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException;
+    public void insert(String keyspace, byte[] key, ColumnParent column_parent, Column column, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException;
 
     /**
      * Insert Columns or SuperColumns across different Column Families for the same row key. batch_mutation is a
@@ -638,21 +635,20 @@ public class Cassandra {
       throw new TApplicationException(TApplicationException.MISSING_RESULT, "get_range_slices failed: unknown result");
     }
 
-    public void insert(String keyspace, byte[] key, ColumnPath column_path, byte[] value, long timestamp, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException
+    public void insert(String keyspace, byte[] key, ColumnParent column_parent, Column column, ConsistencyLevel consistency_level) throws InvalidRequestException, UnavailableException, TimedOutException, TException
     {
-      send_insert(keyspace, key, column_path, value, timestamp, consistency_level);
+      send_insert(keyspace, key, column_parent, column, consistency_level);
       recv_insert();
     }
 
-    public void send_insert(String keyspace, byte[] key, ColumnPath column_path, byte[] value, long timestamp, ConsistencyLevel consistency_level) throws TException
+    public void send_insert(String keyspace, byte[] key, ColumnParent column_parent, Column column, ConsistencyLevel consistency_level) throws TException
     {
       oprot_.writeMessageBegin(new TMessage("insert", TMessageType.CALL, seqid_));
       insert_args args = new insert_args();
       args.keyspace = keyspace;
       args.key = key;
-      args.column_path = column_path;
-      args.value = value;
-      args.timestamp = timestamp;
+      args.column_parent = column_parent;
+      args.column = column;
       args.consistency_level = consistency_level;
       args.write(oprot_);
       oprot_.writeMessageEnd();
@@ -1622,7 +1618,7 @@ public class Cassandra {
         iprot.readMessageEnd();
         insert_result result = new insert_result();
         try {
-          iface_.insert(args.keyspace, args.key, args.column_path, args.value, args.timestamp, args.consistency_level);
+          iface_.insert(args.keyspace, args.key, args.column_parent, args.column, args.consistency_level);
         } catch (InvalidRequestException ire) {
           result.ire = ire;
         } catch (UnavailableException ue) {
@@ -11560,16 +11556,14 @@ public class Cassandra {
 
     private static final TField KEYSPACE_FIELD_DESC = new TField("keyspace", TType.STRING, (short)1);
     private static final TField KEY_FIELD_DESC = new TField("key", TType.STRING, (short)2);
-    private static final TField COLUMN_PATH_FIELD_DESC = new TField("column_path", TType.STRUCT, (short)3);
-    private static final TField VALUE_FIELD_DESC = new TField("value", TType.STRING, (short)4);
-    private static final TField TIMESTAMP_FIELD_DESC = new TField("timestamp", TType.I64, (short)5);
-    private static final TField CONSISTENCY_LEVEL_FIELD_DESC = new TField("consistency_level", TType.I32, (short)6);
+    private static final TField COLUMN_PARENT_FIELD_DESC = new TField("column_parent", TType.STRUCT, (short)3);
+    private static final TField COLUMN_FIELD_DESC = new TField("column", TType.STRUCT, (short)4);
+    private static final TField CONSISTENCY_LEVEL_FIELD_DESC = new TField("consistency_level", TType.I32, (short)5);
 
     public String keyspace;
     public byte[] key;
-    public ColumnPath column_path;
-    public byte[] value;
-    public long timestamp;
+    public ColumnParent column_parent;
+    public Column column;
     /**
      * 
      * @see ConsistencyLevel
@@ -11580,14 +11574,13 @@ public class Cassandra {
     public enum _Fields implements TFieldIdEnum {
       KEYSPACE((short)1, "keyspace"),
       KEY((short)2, "key"),
-      COLUMN_PATH((short)3, "column_path"),
-      VALUE((short)4, "value"),
-      TIMESTAMP((short)5, "timestamp"),
+      COLUMN_PARENT((short)3, "column_parent"),
+      COLUMN((short)4, "column"),
       /**
        * 
        * @see ConsistencyLevel
        */
-      CONSISTENCY_LEVEL((short)6, "consistency_level");
+      CONSISTENCY_LEVEL((short)5, "consistency_level");
 
       private static final Map<Integer, _Fields> byId = new HashMap<Integer, _Fields>();
       private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
@@ -11641,20 +11634,16 @@ public class Cassandra {
     }
 
     // isset id assignments
-    private static final int __TIMESTAMP_ISSET_ID = 0;
-    private BitSet __isset_bit_vector = new BitSet(1);
 
     public static final Map<_Fields, FieldMetaData> metaDataMap = Collections.unmodifiableMap(new EnumMap<_Fields, FieldMetaData>(_Fields.class) {{
       put(_Fields.KEYSPACE, new FieldMetaData("keyspace", TFieldRequirementType.REQUIRED, 
           new FieldValueMetaData(TType.STRING)));
       put(_Fields.KEY, new FieldMetaData("key", TFieldRequirementType.REQUIRED, 
           new FieldValueMetaData(TType.STRING)));
-      put(_Fields.COLUMN_PATH, new FieldMetaData("column_path", TFieldRequirementType.REQUIRED, 
-          new StructMetaData(TType.STRUCT, ColumnPath.class)));
-      put(_Fields.VALUE, new FieldMetaData("value", TFieldRequirementType.REQUIRED, 
-          new FieldValueMetaData(TType.STRING)));
-      put(_Fields.TIMESTAMP, new FieldMetaData("timestamp", TFieldRequirementType.REQUIRED, 
-          new FieldValueMetaData(TType.I64)));
+      put(_Fields.COLUMN_PARENT, new FieldMetaData("column_parent", TFieldRequirementType.REQUIRED, 
+          new StructMetaData(TType.STRUCT, ColumnParent.class)));
+      put(_Fields.COLUMN, new FieldMetaData("column", TFieldRequirementType.REQUIRED, 
+          new StructMetaData(TType.STRUCT, Column.class)));
       put(_Fields.CONSISTENCY_LEVEL, new FieldMetaData("consistency_level", TFieldRequirementType.REQUIRED, 
           new EnumMetaData(TType.ENUM, ConsistencyLevel.class)));
     }});
@@ -11671,18 +11660,15 @@ public class Cassandra {
     public insert_args(
       String keyspace,
       byte[] key,
-      ColumnPath column_path,
-      byte[] value,
-      long timestamp,
+      ColumnParent column_parent,
+      Column column,
       ConsistencyLevel consistency_level)
     {
       this();
       this.keyspace = keyspace;
       this.key = key;
-      this.column_path = column_path;
-      this.value = value;
-      this.timestamp = timestamp;
-      setTimestampIsSet(true);
+      this.column_parent = column_parent;
+      this.column = column;
       this.consistency_level = consistency_level;
     }
 
@@ -11690,8 +11676,6 @@ public class Cassandra {
      * Performs a deep copy on <i>other</i>.
      */
     public insert_args(insert_args other) {
-      __isset_bit_vector.clear();
-      __isset_bit_vector.or(other.__isset_bit_vector);
       if (other.isSetKeyspace()) {
         this.keyspace = other.keyspace;
       }
@@ -11699,14 +11683,12 @@ public class Cassandra {
         this.key = new byte[other.key.length];
         System.arraycopy(other.key, 0, key, 0, other.key.length);
       }
-      if (other.isSetColumn_path()) {
-        this.column_path = new ColumnPath(other.column_path);
+      if (other.isSetColumn_parent()) {
+        this.column_parent = new ColumnParent(other.column_parent);
       }
-      if (other.isSetValue()) {
-        this.value = new byte[other.value.length];
-        System.arraycopy(other.value, 0, value, 0, other.value.length);
+      if (other.isSetColumn()) {
+        this.column = new Column(other.column);
       }
-      this.timestamp = other.timestamp;
       if (other.isSetConsistency_level()) {
         this.consistency_level = other.consistency_level;
       }
@@ -11769,77 +11751,54 @@ public class Cassandra {
       }
     }
 
-    public ColumnPath getColumn_path() {
-      return this.column_path;
+    public ColumnParent getColumn_parent() {
+      return this.column_parent;
     }
 
-    public insert_args setColumn_path(ColumnPath column_path) {
-      this.column_path = column_path;
+    public insert_args setColumn_parent(ColumnParent column_parent) {
+      this.column_parent = column_parent;
       return this;
     }
 
-    public void unsetColumn_path() {
-      this.column_path = null;
+    public void unsetColumn_parent() {
+      this.column_parent = null;
     }
 
-    /** Returns true if field column_path is set (has been asigned a value) and false otherwise */
-    public boolean isSetColumn_path() {
-      return this.column_path != null;
+    /** Returns true if field column_parent is set (has been asigned a value) and false otherwise */
+    public boolean isSetColumn_parent() {
+      return this.column_parent != null;
     }
 
-    public void setColumn_pathIsSet(boolean value) {
+    public void setColumn_parentIsSet(boolean value) {
       if (!value) {
-        this.column_path = null;
+        this.column_parent = null;
       }
     }
 
-    public byte[] getValue() {
-      return this.value;
+    public Column getColumn() {
+      return this.column;
     }
 
-    public insert_args setValue(byte[] value) {
-      this.value = value;
+    public insert_args setColumn(Column column) {
+      this.column = column;
       return this;
     }
 
-    public void unsetValue() {
-      this.value = null;
+    public void unsetColumn() {
+      this.column = null;
     }
 
-    /** Returns true if field value is set (has been asigned a value) and false otherwise */
-    public boolean isSetValue() {
-      return this.value != null;
+    /** Returns true if field column is set (has been asigned a value) and false otherwise */
+    public boolean isSetColumn() {
+      return this.column != null;
     }
 
-    public void setValueIsSet(boolean value) {
+    public void setColumnIsSet(boolean value) {
       if (!value) {
-        this.value = null;
+        this.column = null;
       }
     }
 
-    public long getTimestamp() {
-      return this.timestamp;
-    }
-
-    public insert_args setTimestamp(long timestamp) {
-      this.timestamp = timestamp;
-      setTimestampIsSet(true);
-      return this;
-    }
-
-    public void unsetTimestamp() {
-      __isset_bit_vector.clear(__TIMESTAMP_ISSET_ID);
-    }
-
-    /** Returns true if field timestamp is set (has been asigned a value) and false otherwise */
-    public boolean isSetTimestamp() {
-      return __isset_bit_vector.get(__TIMESTAMP_ISSET_ID);
-    }
-
-    public void setTimestampIsSet(boolean value) {
-      __isset_bit_vector.set(__TIMESTAMP_ISSET_ID, value);
-    }
-
     /**
      * 
      * @see ConsistencyLevel
@@ -11890,27 +11849,19 @@ public class Cassandra {
         }
         break;
 
-      case COLUMN_PATH:
+      case COLUMN_PARENT:
         if (value == null) {
-          unsetColumn_path();
+          unsetColumn_parent();
         } else {
-          setColumn_path((ColumnPath)value);
+          setColumn_parent((ColumnParent)value);
         }
         break;
 
-      case VALUE:
+      case COLUMN:
         if (value == null) {
-          unsetValue();
+          unsetColumn();
         } else {
-          setValue((byte[])value);
-        }
-        break;
-
-      case TIMESTAMP:
-        if (value == null) {
-          unsetTimestamp();
-        } else {
-          setTimestamp((Long)value);
+          setColumn((Column)value);
         }
         break;
 
@@ -11937,14 +11888,11 @@ public class Cassandra {
       case KEY:
         return getKey();
 
-      case COLUMN_PATH:
-        return getColumn_path();
-
-      case VALUE:
-        return getValue();
+      case COLUMN_PARENT:
+        return getColumn_parent();
 
-      case TIMESTAMP:
-        return new Long(getTimestamp());
+      case COLUMN:
+        return getColumn();
 
       case CONSISTENCY_LEVEL:
         return getConsistency_level();
@@ -11964,12 +11912,10 @@ public class Cassandra {
         return isSetKeyspace();
       case KEY:
         return isSetKey();
-      case COLUMN_PATH:
-        return isSetColumn_path();
-      case VALUE:
-        return isSetValue();
-      case TIMESTAMP:
-        return isSetTimestamp();
+      case COLUMN_PARENT:
+        return isSetColumn_parent();
+      case COLUMN:
+        return isSetColumn();
       case CONSISTENCY_LEVEL:
         return isSetConsistency_level();
       }
@@ -12011,30 +11957,21 @@ public class Cassandra {
           return false;
       }
 
-      boolean this_present_column_path = true && this.isSetColumn_path();
-      boolean that_present_column_path = true && that.isSetColumn_path();
-      if (this_present_column_path || that_present_column_path) {
-        if (!(this_present_column_path && that_present_column_path))
-          return false;
-        if (!this.column_path.equals(that.column_path))
-          return false;
-      }
-
-      boolean this_present_value = true && this.isSetValue();
-      boolean that_present_value = true && that.isSetValue();
-      if (this_present_value || that_present_value) {
-        if (!(this_present_value && that_present_value))
+      boolean this_present_column_parent = true && this.isSetColumn_parent();
+      boolean that_present_column_parent = true && that.isSetColumn_parent();
+      if (this_present_column_parent || that_present_column_parent) {
+        if (!(this_present_column_parent && that_present_column_parent))
           return false;
-        if (!java.util.Arrays.equals(this.value, that.value))
+        if (!this.column_parent.equals(that.column_parent))
           return false;
       }
 
-      boolean this_present_timestamp = true;
-      boolean that_present_timestamp = true;
-      if (this_present_timestamp || that_present_timestamp) {
-        if (!(this_present_timestamp && that_present_timestamp))
+      boolean this_present_column = true && this.isSetColumn();
+      boolean that_present_column = true && that.isSetColumn();
+      if (this_present_column || that_present_column) {
+        if (!(this_present_column && that_present_column))
           return false;
-        if (this.timestamp != that.timestamp)
+        if (!this.column.equals(that.column))
           return false;
       }
 
@@ -12081,29 +12018,20 @@ public class Cassandra {
           return lastComparison;
         }
       }
-      lastComparison = Boolean.valueOf(isSetColumn_path()).compareTo(typedOther.isSetColumn_path());
-      if (lastComparison != 0) {
-        return lastComparison;
-      }
-      if (isSetColumn_path()) {        lastComparison = TBaseHelper.compareTo(column_path, typedOther.column_path);
-        if (lastComparison != 0) {
-          return lastComparison;
-        }
-      }
-      lastComparison = Boolean.valueOf(isSetValue()).compareTo(typedOther.isSetValue());
+      lastComparison = Boolean.valueOf(isSetColumn_parent()).compareTo(typedOther.isSetColumn_parent());
       if (lastComparison != 0) {
         return lastComparison;
       }
-      if (isSetValue()) {        lastComparison = TBaseHelper.compareTo(value, typedOther.value);
+      if (isSetColumn_parent()) {        lastComparison = TBaseHelper.compareTo(column_parent, typedOther.column_parent);
         if (lastComparison != 0) {
           return lastComparison;
         }
       }
-      lastComparison = Boolean.valueOf(isSetTimestamp()).compareTo(typedOther.isSetTimestamp());
+      lastComparison = Boolean.valueOf(isSetColumn()).compareTo(typedOther.isSetColumn());
       if (lastComparison != 0) {
         return lastComparison;
       }
-      if (isSetTimestamp()) {        lastComparison = TBaseHelper.compareTo(timestamp, typedOther.timestamp);
+      if (isSetColumn()) {        lastComparison = TBaseHelper.compareTo(column, typedOther.column);
         if (lastComparison != 0) {
           return lastComparison;
         }
@@ -12144,30 +12072,23 @@ public class Cassandra {
               TProtocolUtil.skip(iprot, field.type);
             }
             break;
-          case 3: // COLUMN_PATH
+          case 3: // COLUMN_PARENT
             if (field.type == TType.STRUCT) {
-              this.column_path = new ColumnPath();
-              this.column_path.read(iprot);
-            } else { 
-              TProtocolUtil.skip(iprot, field.type);
-            }
-            break;
-          case 4: // VALUE
-            if (field.type == TType.STRING) {
-              this.value = iprot.readBinary();
+              this.column_parent = new ColumnParent();
+              this.column_parent.read(iprot);
             } else { 
               TProtocolUtil.skip(iprot, field.type);
             }
             break;
-          case 5: // TIMESTAMP
-            if (field.type == TType.I64) {
-              this.timestamp = iprot.readI64();
-              setTimestampIsSet(true);
+          case 4: // COLUMN
+            if (field.type == TType.STRUCT) {
+              this.column = new Column();
+              this.column.read(iprot);
             } else { 
               TProtocolUtil.skip(iprot, field.type);
             }
             break;
-          case 6: // CONSISTENCY_LEVEL
+          case 5: // CONSISTENCY_LEVEL
             if (field.type == TType.I32) {
               this.consistency_level = ConsistencyLevel.findByValue(iprot.readI32());
             } else { 
@@ -12182,9 +12103,6 @@ public class Cassandra {
       iprot.readStructEnd();
 
       // check for required fields of primitive type, which can't be checked in the validate method
-      if (!isSetTimestamp()) {
-        throw new TProtocolException("Required field 'timestamp' was not found in serialized data! Struct: " + toString());
-      }
       validate();
     }
 
@@ -12202,19 +12120,16 @@ public class Cassandra {
         oprot.writeBinary(this.key);
         oprot.writeFieldEnd();
       }
-      if (this.column_path != null) {
-        oprot.writeFieldBegin(COLUMN_PATH_FIELD_DESC);
-        this.column_path.write(oprot);
+      if (this.column_parent != null) {
+        oprot.writeFieldBegin(COLUMN_PARENT_FIELD_DESC);
+        this.column_parent.write(oprot);
         oprot.writeFieldEnd();
       }
-      if (this.value != null) {
-        oprot.writeFieldBegin(VALUE_FIELD_DESC);
-        oprot.writeBinary(this.value);
+      if (this.column != null) {
+        oprot.writeFieldBegin(COLUMN_FIELD_DESC);
+        this.column.write(oprot);
         oprot.writeFieldEnd();
       }
-      oprot.writeFieldBegin(TIMESTAMP_FIELD_DESC);
-      oprot.writeI64(this.timestamp);
-      oprot.writeFieldEnd();
       if (this.consistency_level != null) {
         oprot.writeFieldBegin(CONSISTENCY_LEVEL_FIELD_DESC);
         oprot.writeI32(this.consistency_level.getValue());
@@ -12250,31 +12165,22 @@ public class Cassandra {
       }
       first = false;
       if (!first) sb.append(", ");
-      sb.append("column_path:");
-      if (this.column_path == null) {
+      sb.append("column_parent:");
+      if (this.column_parent == null) {
         sb.append("null");
       } else {
-        sb.append(this.column_path);
+        sb.append(this.column_parent);
       }
       first = false;
       if (!first) sb.append(", ");
-      sb.append("value:");
-      if (this.value == null) {
+      sb.append("column:");
+      if (this.column == null) {
         sb.append("null");
       } else {
-          int __value_size = Math.min(this.value.length, 128);
-          for (int i = 0; i < __value_size; i++) {
-            if (i != 0) sb.append(" ");
-            sb.append(Integer.toHexString(this.value[i]).length() > 1 ? Integer.toHexString(this.value[i]).substring(Integer.toHexString(this.value[i]).length() - 2).toUpperCase() : "0" + Integer.toHexString(this.value[i]).toUpperCase());
-          }
-          if (this.value.length > 128) sb.append(" ...");
+        sb.append(this.column);
       }
       first = false;
       if (!first) sb.append(", ");
-      sb.append("timestamp:");
-      sb.append(this.timestamp);
-      first = false;
-      if (!first) sb.append(", ");
       sb.append("consistency_level:");
       if (this.consistency_level == null) {
         sb.append("null");
@@ -12294,13 +12200,12 @@ public class Cassandra {
       if (key == null) {
         throw new TProtocolException("Required field 'key' was not present! Struct: " + toString());
       }
-      if (column_path == null) {
-        throw new TProtocolException("Required field 'column_path' was not present! Struct: " + toString());
+      if (column_parent == null) {
+        throw new TProtocolException("Required field 'column_parent' was not present! Struct: " + toString());
       }
-      if (value == null) {
-        throw new TProtocolException("Required field 'value' was not present! Struct: " + toString());
+      if (column == null) {
+        throw new TProtocolException("Required field 'column' was not present! Struct: " + toString());
       }
-      // alas, we cannot check 'timestamp' because it's a primitive and you chose the non-beans generator.
       if (consistency_level == null) {
         throw new TProtocolException("Required field 'consistency_level' was not present! Struct: " + toString());
       }

Modified: cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java?rev=935088&r1=935087&r2=935088&view=diff
==============================================================================
--- cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java (original)
+++ cassandra/trunk/interface/thrift/gen-java/org/apache/cassandra/thrift/Column.java Fri Apr 16 22:04:46 2010
@@ -50,6 +50,9 @@ import org.apache.thrift.protocol.*;
  *        is used as a key to its value.
  * @param value. Some data
  * @param timestamp. Used to record when data was sent to be written.
+ * @param ttl. A delay (in seconds) after which the column will be automatically deleted. If this parameter is not
+ *             provided or is <= 0, the column will never be deleted automatically (and will have no ttl when queried).
+ *             Note that, if set, the column will be deleted from a node ttl seconds after the column reach the node.
  */
 public class Column implements TBase<Column._Fields>, java.io.Serializable, Cloneable, Comparable<Column> {
   private static final TStruct STRUCT_DESC = new TStruct("Column");
@@ -57,16 +60,19 @@ public class Column implements TBase<Col
   private static final TField NAME_FIELD_DESC = new TField("name", TType.STRING, (short)1);
   private static final TField VALUE_FIELD_DESC = new TField("value", TType.STRING, (short)2);
   private static final TField TIMESTAMP_FIELD_DESC = new TField("timestamp", TType.I64, (short)3);
+  private static final TField TTL_FIELD_DESC = new TField("ttl", TType.I32, (short)4);
 
   public byte[] name;
   public byte[] value;
   public long timestamp;
+  public int ttl;
 
   /** The set of fields this struct contains, along with convenience methods for finding and manipulating them. */
   public enum _Fields implements TFieldIdEnum {
     NAME((short)1, "name"),
     VALUE((short)2, "value"),
-    TIMESTAMP((short)3, "timestamp");
+    TIMESTAMP((short)3, "timestamp"),
+    TTL((short)4, "ttl");
 
     private static final Map<Integer, _Fields> byId = new HashMap<Integer, _Fields>();
     private static final Map<String, _Fields> byName = new HashMap<String, _Fields>();
@@ -121,7 +127,8 @@ public class Column implements TBase<Col
 
   // isset id assignments
   private static final int __TIMESTAMP_ISSET_ID = 0;
-  private BitSet __isset_bit_vector = new BitSet(1);
+  private static final int __TTL_ISSET_ID = 1;
+  private BitSet __isset_bit_vector = new BitSet(2);
 
   public static final Map<_Fields, FieldMetaData> metaDataMap = Collections.unmodifiableMap(new EnumMap<_Fields, FieldMetaData>(_Fields.class) {{
     put(_Fields.NAME, new FieldMetaData("name", TFieldRequirementType.REQUIRED, 
@@ -130,6 +137,8 @@ public class Column implements TBase<Col
         new FieldValueMetaData(TType.STRING)));
     put(_Fields.TIMESTAMP, new FieldMetaData("timestamp", TFieldRequirementType.REQUIRED, 
         new FieldValueMetaData(TType.I64)));
+    put(_Fields.TTL, new FieldMetaData("ttl", TFieldRequirementType.OPTIONAL, 
+        new FieldValueMetaData(TType.I32)));
   }});
 
   static {
@@ -166,6 +175,7 @@ public class Column implements TBase<Col
       System.arraycopy(other.value, 0, value, 0, other.value.length);
     }
     this.timestamp = other.timestamp;
+    this.ttl = other.ttl;
   }
 
   public Column deepCopy() {
@@ -248,6 +258,29 @@ public class Column implements TBase<Col
     __isset_bit_vector.set(__TIMESTAMP_ISSET_ID, value);
   }
 
+  public int getTtl() {
+    return this.ttl;
+  }
+
+  public Column setTtl(int ttl) {
+    this.ttl = ttl;
+    setTtlIsSet(true);
+    return this;
+  }
+
+  public void unsetTtl() {
+    __isset_bit_vector.clear(__TTL_ISSET_ID);
+  }
+
+  /** Returns true if field ttl is set (has been asigned a value) and false otherwise */
+  public boolean isSetTtl() {
+    return __isset_bit_vector.get(__TTL_ISSET_ID);
+  }
+
+  public void setTtlIsSet(boolean value) {
+    __isset_bit_vector.set(__TTL_ISSET_ID, value);
+  }
+
   public void setFieldValue(_Fields field, Object value) {
     switch (field) {
     case NAME:
@@ -274,6 +307,14 @@ public class Column implements TBase<Col
       }
       break;
 
+    case TTL:
+      if (value == null) {
+        unsetTtl();
+      } else {
+        setTtl((Integer)value);
+      }
+      break;
+
     }
   }
 
@@ -292,6 +333,9 @@ public class Column implements TBase<Col
     case TIMESTAMP:
       return new Long(getTimestamp());
 
+    case TTL:
+      return new Integer(getTtl());
+
     }
     throw new IllegalStateException();
   }
@@ -309,6 +353,8 @@ public class Column implements TBase<Col
       return isSetValue();
     case TIMESTAMP:
       return isSetTimestamp();
+    case TTL:
+      return isSetTtl();
     }
     throw new IllegalStateException();
   }
@@ -357,6 +403,15 @@ public class Column implements TBase<Col
         return false;
     }
 
+    boolean this_present_ttl = true && this.isSetTtl();
+    boolean that_present_ttl = true && that.isSetTtl();
+    if (this_present_ttl || that_present_ttl) {
+      if (!(this_present_ttl && that_present_ttl))
+        return false;
+      if (this.ttl != that.ttl)
+        return false;
+    }
+
     return true;
   }
 
@@ -400,6 +455,15 @@ public class Column implements TBase<Col
         return lastComparison;
       }
     }
+    lastComparison = Boolean.valueOf(isSetTtl()).compareTo(typedOther.isSetTtl());
+    if (lastComparison != 0) {
+      return lastComparison;
+    }
+    if (isSetTtl()) {      lastComparison = TBaseHelper.compareTo(ttl, typedOther.ttl);
+      if (lastComparison != 0) {
+        return lastComparison;
+      }
+    }
     return 0;
   }
 
@@ -435,6 +499,14 @@ public class Column implements TBase<Col
             TProtocolUtil.skip(iprot, field.type);
           }
           break;
+        case 4: // TTL
+          if (field.type == TType.I32) {
+            this.ttl = iprot.readI32();
+            setTtlIsSet(true);
+          } else { 
+            TProtocolUtil.skip(iprot, field.type);
+          }
+          break;
         default:
           TProtocolUtil.skip(iprot, field.type);
       }
@@ -466,6 +538,11 @@ public class Column implements TBase<Col
     oprot.writeFieldBegin(TIMESTAMP_FIELD_DESC);
     oprot.writeI64(this.timestamp);
     oprot.writeFieldEnd();
+    if (isSetTtl()) {
+      oprot.writeFieldBegin(TTL_FIELD_DESC);
+      oprot.writeI32(this.ttl);
+      oprot.writeFieldEnd();
+    }
     oprot.writeFieldStop();
     oprot.writeStructEnd();
   }
@@ -504,6 +581,12 @@ public class Column implements TBase<Col
     sb.append("timestamp:");
     sb.append(this.timestamp);
     first = false;
+    if (isSetTtl()) {
+      if (!first) sb.append(", ");
+      sb.append("ttl:");
+      sb.append(this.ttl);
+      first = false;
+    }
     sb.append(")");
     return sb.toString();
   }

Modified: cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java?rev=935088&r1=935087&r2=935088&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/cli/CliClient.java Fri Apr 16 22:04:46 2010
@@ -411,8 +411,8 @@ public class CliClient 
         }
         
         // do the insert
-        thriftClient_.insert(tableName, key.getBytes(), new ColumnPath(columnFamily).setSuper_column(superColumnName).setColumn(columnName),
-                             value.getBytes(), timestampMicros(), ConsistencyLevel.ONE);
+        thriftClient_.insert(tableName, key.getBytes(), new ColumnParent(columnFamily).setSuper_column(superColumnName),
+                             new Column(columnName, value.getBytes(), timestampMicros()), ConsistencyLevel.ONE);
         
         css_.out.println("Value inserted.");
     }

Modified: cassandra/trunk/src/java/org/apache/cassandra/db/Column.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/Column.java?rev=935088&r1=935087&r2=935088&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/Column.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/Column.java Fri Apr 16 22:04:46 2010
@@ -160,7 +160,7 @@ public class Column implements IColumn
         try
         {
             buffer.writeLong(timestamp);
-            buffer.writeBoolean(isMarkedForDelete());
+            buffer.writeByte((isMarkedForDelete()) ? ColumnSerializer.DELETION_MASK : 0);
         }
         catch (IOException e)
         {

Modified: cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java?rev=935088&r1=935087&r2=935088&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/ColumnFamily.java Fri Apr 16 22:04:46 2010
@@ -181,6 +181,17 @@ public class ColumnFamily implements ICo
         addColumn(path.superColumnName, new DeletedColumn(path.columnName, localDeletionTime, timestamp));
     }
 
+    public void addColumn(QueryPath path, byte[] value, long timestamp, int timeToLive)
+    {
+        assert path.columnName != null : path;
+        Column column;
+        if (timeToLive > 0)
+            column = new ExpiringColumn(path.columnName, value, timestamp, timeToLive);
+        else
+            column = new Column(path.columnName, value, timestamp);
+        addColumn(path.superColumnName, column);
+    }
+
     public void deleteColumn(QueryPath path, int localDeletionTime, long timestamp)
     {
         assert path.columnName != null : path;

Modified: cassandra/trunk/src/java/org/apache/cassandra/db/ColumnSerializer.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/ColumnSerializer.java?rev=935088&r1=935087&r2=935088&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/ColumnSerializer.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/ColumnSerializer.java Fri Apr 16 22:04:46 2010
@@ -26,14 +26,25 @@ import java.io.*;
 import org.apache.cassandra.io.ICompactSerializer2;
 import org.apache.cassandra.utils.FBUtilities;
 
+import java.nio.ByteBuffer;
+
 public class ColumnSerializer implements ICompactSerializer2<IColumn>
 {
+    public final static int DELETION_MASK = 0x01;
+    public final static int EXPIRATION_MASK = 0x02;
+
     public void serialize(IColumn column, DataOutput dos)
     {
         FBUtilities.writeShortByteArray(column.name(), dos);
         try
         {
-            dos.writeBoolean(column.isMarkedForDelete());
+            if (column instanceof ExpiringColumn) {
+              dos.writeByte(EXPIRATION_MASK);
+              dos.writeInt(((ExpiringColumn) column).getTimeToLive());
+              dos.writeInt(column.getLocalDeletionTime());
+            } else {
+              dos.writeByte((column.isMarkedForDelete()) ? DELETION_MASK : 0);
+            }
             dos.writeLong(column.timestamp());
             FBUtilities.writeByteArray(column.value(), dos);
         }
@@ -46,18 +57,36 @@ public class ColumnSerializer implements
     public Column deserialize(DataInput dis) throws IOException
     {
         byte[] name = FBUtilities.readShortByteArray(dis);
-        boolean delete = dis.readBoolean();
-        long ts = dis.readLong();
-        int length = dis.readInt();
-        if (length < 0)
+        int b = dis.readUnsignedByte();
+        if (FBUtilities.testBitUsingBitMask(b, EXPIRATION_MASK))
         {
-            throw new IOException("Corrupt (negative) value length encountered");
+            int ttl = dis.readInt();
+            int expiration = dis.readInt();
+            long ts = dis.readLong();
+            byte[] value = FBUtilities.readByteArray(dis);
+            if ((int) (System.currentTimeMillis() / 1000 ) > expiration)
+            {
+                // the column is now expired, we can safely return a simple
+                // tombstone
+                ByteBuffer bytes = ByteBuffer.allocate(4);
+                bytes.putInt(expiration);
+                return new DeletedColumn(name, bytes.array(), ts);
+            }
+            else
+            {
+                return new ExpiringColumn(name, value, ts, ttl, expiration);
+            }
         }
-        byte[] value = new byte[length];
-        if (length > 0)
+        else
         {
-            dis.readFully(value);
+            boolean delete = FBUtilities.testBitUsingBitMask(b, DELETION_MASK);
+            long ts = dis.readLong();
+            byte[] value = FBUtilities.readByteArray(dis);
+            if (FBUtilities.testBitUsingBitMask(b, DELETION_MASK)) {
+                return new DeletedColumn(name, value, ts);
+            } else {
+                return new Column(name, value, ts);
+            }
         }
-        return delete ? new DeletedColumn(name, value, ts) : new Column(name, value, ts);
     }
 }

Added: cassandra/trunk/src/java/org/apache/cassandra/db/ExpiringColumn.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/ExpiringColumn.java?rev=935088&view=auto
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/ExpiringColumn.java (added)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/ExpiringColumn.java Fri Apr 16 22:04:46 2010
@@ -0,0 +1,116 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.cassandra.db;
+
+import java.security.MessageDigest;
+import java.io.IOException;
+
+import org.apache.log4j.Logger;
+
+import org.apache.cassandra.db.marshal.AbstractType;
+import org.apache.cassandra.io.util.DataOutputBuffer;
+
+/**
+ * Alternative to Column that have an expiring time.
+ * ExpiringColumn is immutable (as Column is).
+ *
+ * Note that ExpiringColumn does not override Column.getMarkedForDeleteAt,
+ * which means that it's in the somewhat unintuitive position of being deleted (after its expiration)
+ * without having a time-at-which-it-became-deleted.  (Because ttl is a server-side measurement,
+ * we can't mix it with the timestamp field, which is client-supplied and whose resolution we
+ * can't assume anything about.)
+ */
+public class ExpiringColumn extends Column
+{
+    private static Logger logger = Logger.getLogger(ExpiringColumn.class);
+
+    private final int localExpirationTime;
+    private final int timeToLive;
+
+    public ExpiringColumn(byte[] name, byte[] value, long timestamp, int timeToLive)
+    {
+      this(name, value, timestamp, timeToLive, (int) (System.currentTimeMillis() / 1000) + timeToLive);
+    }
+
+    public ExpiringColumn(byte[] name, byte[] value, long timestamp, int timeToLive, int localExpirationTime)
+    {
+        super(name, value, timestamp);
+        assert timeToLive != 0;
+        assert localExpirationTime != 0;
+        this.timeToLive = timeToLive;
+        this.localExpirationTime = localExpirationTime;
+    }
+
+    public int getTimeToLive()
+    {
+        return timeToLive;
+    }
+
+    @Override
+    public boolean isMarkedForDelete()
+    {
+        return (int) (System.currentTimeMillis() / 1000 ) > localExpirationTime;
+    }
+
+    @Override
+    public int size()
+    {
+        /*
+         * An expired column adds to a Column : 
+         *    4 bytes for the localExpirationTime
+         *  + 4 bytes for the timeToLive
+        */
+        return super.size() + DBConstants.intSize_ + DBConstants.intSize_;
+    }
+
+    @Override
+    public void updateDigest(MessageDigest digest)
+    {
+        digest.update(name());
+        digest.update(value());
+        DataOutputBuffer buffer = new DataOutputBuffer();
+        try
+        {
+            buffer.writeLong(timestamp());
+            buffer.writeByte(ColumnSerializer.EXPIRATION_MASK);
+            buffer.writeInt(timeToLive);
+        }
+        catch (IOException e)
+        {
+            throw new RuntimeException(e);
+        }
+        digest.update(buffer.getData(), 0, buffer.getLength());
+    }
+
+    @Override
+    public int getLocalDeletionTime()
+    {
+        return localExpirationTime;
+    }
+
+    @Override
+    public String getString(AbstractType comparator)
+    {
+        StringBuilder sb = new StringBuilder();
+        sb.append(super.getString(comparator));
+        sb.append("!");
+        sb.append(timeToLive);
+        return sb.toString();
+    }
+}

Modified: cassandra/trunk/src/java/org/apache/cassandra/db/RowMutation.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/db/RowMutation.java?rev=935088&r1=935087&r2=935088&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/db/RowMutation.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/db/RowMutation.java Fri Apr 16 22:04:46 2010
@@ -148,18 +148,24 @@ public class RowMutation
      * param @ cf - column name as <column family>:<column>
      * param @ value - value associated with the column
      * param @ timestamp - timestamp associated with this data.
+     * param @ timeToLive - ttl for the column, 0 for standard (non expiring) columns
     */
-    public void add(QueryPath path, byte[] value, long timestamp)
+    public void add(QueryPath path, byte[] value, long timestamp, int timeToLive)
     {
         ColumnFamily columnFamily = modifications_.get(path.columnFamilyName);
         if (columnFamily == null)
         {
             columnFamily = ColumnFamily.create(table_, path.columnFamilyName);
         }
-        columnFamily.addColumn(path, value, timestamp);
+        columnFamily.addColumn(path, value, timestamp, timeToLive);
         modifications_.put(path.columnFamilyName, columnFamily);
     }
 
+    public void add(QueryPath path, byte[] value, long timestamp)
+    {
+        add(path, value, timestamp, 0);
+    }
+
     public void delete(QueryPath path, long timestamp)
     {
         assert path.columnFamilyName != null;
@@ -254,13 +260,13 @@ public class RowMutation
                     assert cosc.super_column != null;
                     for (org.apache.cassandra.thrift.Column column : cosc.super_column.columns)
                     {
-                        rm.add(new QueryPath(cfName, cosc.super_column.name, column.name), column.value, column.timestamp);
+                        rm.add(new QueryPath(cfName, cosc.super_column.name, column.name), column.value, column.timestamp, column.getTtl());
                     }
                 }
                 else
                 {
                     assert cosc.super_column == null;
-                    rm.add(new QueryPath(cfName, null, cosc.column.name), cosc.column.value, cosc.column.timestamp);
+                    rm.add(new QueryPath(cfName, null, cosc.column.name), cosc.column.value, cosc.column.timestamp, cosc.column.getTtl());
                 }
             }
         }

Modified: cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java?rev=935088&r1=935087&r2=935088&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/thrift/CassandraServer.java Fri Apr 16 22:04:46 2010
@@ -139,6 +139,10 @@ public class CassandraServer implements 
                 continue;
             }
             Column thrift_column = new Column(column.name(), column.value(), column.timestamp());
+            if (column instanceof ExpiringColumn)
+            {
+                thrift_column.setTtl(((ExpiringColumn) column).getTimeToLive());
+            }
             thriftColumns.add(thrift_column);
         }
 
@@ -155,6 +159,10 @@ public class CassandraServer implements 
                 continue;
             }
             Column thrift_column = new Column(column.name(), column.value(), column.timestamp());
+            if (column instanceof ExpiringColumn)
+            {
+                thrift_column.setTtl(((ExpiringColumn) column).getTimeToLive());
+            }
             thriftColumns.add(new ColumnOrSuperColumn().setColumn(thrift_column));
         }
 
@@ -346,7 +354,7 @@ public class CassandraServer implements 
         return get_slice(table, key, column_parent, predicate, consistency_level).size();
     }
 
-    public void insert(String table, byte[] key, ColumnPath column_path, byte[] value, long timestamp, ConsistencyLevel consistency_level)
+    public void insert(String table, byte[] key, ColumnParent column_parent, Column column, ConsistencyLevel consistency_level)
     throws InvalidRequestException, UnavailableException, TimedOutException
     {
         if (logger.isDebugEnabled())
@@ -355,12 +363,13 @@ public class CassandraServer implements 
         checkLoginAuthorized(AccessLevel.READWRITE);
 
         ThriftValidation.validateKey(key);
-        ThriftValidation.validateColumnPath(table, column_path);
+        ThriftValidation.validateColumnParent(table, column_parent);
+        ThriftValidation.validateColumn(table, column_parent, column.name);
 
         RowMutation rm = new RowMutation(table, key);
         try
         {
-            rm.add(new QueryPath(column_path), value, timestamp);
+            rm.add(new QueryPath(column_parent.column_family, column_parent.super_column, column.name), column.value, column.timestamp, Math.max(column.ttl, 0));
         }
         catch (MarshalException e)
         {
@@ -841,4 +850,3 @@ public class CassandraServer implements 
 
     // main method moved to CassandraDaemon
 }
-    
\ No newline at end of file

Modified: cassandra/trunk/src/java/org/apache/cassandra/thrift/ThriftValidation.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/thrift/ThriftValidation.java?rev=935088&r1=935087&r2=935088&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/thrift/ThriftValidation.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/thrift/ThriftValidation.java Fri Apr 16 22:04:46 2010
@@ -273,6 +273,11 @@ public class ThriftValidation
             validateColumns(keyspace, cfName, scName, predicate.column_names);
     }
 
+    public static void validateColumn(String keyspace, ColumnParent column_parent, byte[] column_name) throws InvalidRequestException
+    {
+        validateColumns(keyspace, column_parent, Arrays.asList(column_name));
+    }
+
     public static void validatePredicate(String keyspace, ColumnParent column_parent, SlicePredicate predicate)
             throws InvalidRequestException
     {

Modified: cassandra/trunk/src/java/org/apache/cassandra/utils/FBUtilities.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/utils/FBUtilities.java?rev=935088&r1=935087&r2=935088&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/utils/FBUtilities.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/utils/FBUtilities.java Fri Apr 16 22:04:46 2010
@@ -309,6 +309,21 @@ public class FBUtilities
         out.write(bytes);
     }
 
+    public static byte[] readByteArray(DataInput in) throws IOException
+    {
+        int length = in.readInt();
+        if (length < 0)
+        {
+            throw new IOException("Corrupt (negative) value length encountered");
+        }
+        byte[] value = new byte[length];
+        if (length > 0)
+        {
+            in.readFully(value);
+        }
+        return value;
+    }
+
     public static void writeShortByteArray(byte[] name, DataOutput out)
     {
         int length = name.length;
@@ -485,4 +500,17 @@ public class FBUtilities
         }
         return utflen;
     }
+
+    /**
+     * Test if a particular bit is set using a bit mask.
+     *
+     * @param v the value in which a bit must be tested
+     * @param mask the bit mask use to select a bit of <code>v</code>
+     * @return true if the bit of <code>v</code> selected by <code>mask<code>
+     * is set, false otherwise.
+     */
+    public static boolean testBitUsingBitMask(int v, int mask)
+    {
+        return (v & mask) != 0;
+    }
 }

Modified: cassandra/trunk/test/system/test_thrift_server.py
URL: http://svn.apache.org/viewvc/cassandra/trunk/test/system/test_thrift_server.py?rev=935088&r1=935087&r2=935088&view=diff
==============================================================================
--- cassandra/trunk/test/system/test_thrift_server.py (original)
+++ cassandra/trunk/test/system/test_thrift_server.py Fri Apr 16 22:04:46 2010
@@ -68,8 +68,8 @@ def _insert_multi(keys, block=True):
         consistencyLevel = ConsistencyLevel.ZERO
 
     for key in keys:
-        client.insert('Keyspace1', key, ColumnPath('Standard1', column='c1'), 'value1', 0, consistencyLevel)
-        client.insert('Keyspace1', key, ColumnPath('Standard1', column='c2'), 'value2', 0, consistencyLevel)
+        client.insert('Keyspace1', key, ColumnParent('Standard1'), Column('c1', 'value1', 0), consistencyLevel)
+        client.insert('Keyspace1', key, ColumnParent('Standard1'), Column('c2', 'value2', 0), consistencyLevel)
 
 def _insert_multi_batch(keys, block):
     cfmap = {'Standard1': [ColumnOrSuperColumn(c) for c in _SIMPLE_COLUMNS],
@@ -103,15 +103,15 @@ def _verify_simple():
     assert L == _SIMPLE_COLUMNS, L
 
 def _insert_super(key='key1'):
-    client.insert('Keyspace1', key, ColumnPath('Super1', 'sc1', _i64(4)), 'value4', 0, ConsistencyLevel.ZERO)
-    client.insert('Keyspace1', key, ColumnPath('Super1', 'sc2', _i64(5)), 'value5', 0, ConsistencyLevel.ZERO)
-    client.insert('Keyspace1', key, ColumnPath('Super1', 'sc2', _i64(6)), 'value6', 0, ConsistencyLevel.ZERO)
+    client.insert('Keyspace1', key, ColumnParent('Super1', 'sc1'), Column(_i64(4), 'value4', 0), ConsistencyLevel.ZERO)
+    client.insert('Keyspace1', key, ColumnParent('Super1', 'sc2'), Column(_i64(5), 'value5', 0), ConsistencyLevel.ZERO)
+    client.insert('Keyspace1', key, ColumnParent('Super1', 'sc2'), Column(_i64(6), 'value6', 0), ConsistencyLevel.ZERO)
     time.sleep(0.1)
 
 def _insert_range():
-    client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='c1'), 'value1', 0, ConsistencyLevel.ONE)
-    client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='c2'), 'value2', 0, ConsistencyLevel.ONE)
-    client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='c3'), 'value3', 0, ConsistencyLevel.ONE)
+    client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('c1', 'value1', 0), ConsistencyLevel.ONE)
+    client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('c2', 'value2', 0), ConsistencyLevel.ONE)
+    client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('c3', 'value3', 0), ConsistencyLevel.ONE)
     time.sleep(0.1)
 
 def _verify_range():
@@ -136,10 +136,10 @@ def _verify_range():
     assert len(result) == 2, result
 
 def _insert_super_range():
-    client.insert('Keyspace1', 'key1', ColumnPath('Super1', 'sc1', _i64(4)), 'value4', 0, False)
-    client.insert('Keyspace1', 'key1', ColumnPath('Super1', 'sc2', _i64(5)), 'value5', 0, False)
-    client.insert('Keyspace1', 'key1', ColumnPath('Super1', 'sc2', _i64(6)), 'value6', 0, False)
-    client.insert('Keyspace1', 'key1', ColumnPath('Super1', 'sc3', _i64(7)), 'value7', 0, False)
+    client.insert('Keyspace1', 'key1', ColumnParent('Super1', 'sc1'), Column(_i64(4), 'value4', 0), False)
+    client.insert('Keyspace1', 'key1', ColumnParent('Super1', 'sc2'), Column(_i64(5), 'value5', 0), False)
+    client.insert('Keyspace1', 'key1', ColumnParent('Super1', 'sc2'), Column(_i64(6), 'value6', 0), False)
+    client.insert('Keyspace1', 'key1', ColumnParent('Super1', 'sc3'), Column(_i64(7), 'value7', 0), False)
     time.sleep(0.1)
 
 def _verify_super_range():
@@ -247,7 +247,7 @@ class TestMutations(ThriftTester):
         L = []
         for i in long_xrange(0, 104294967296, 429496729):
             name = _i64(i)
-            client.insert('Keyspace1', 'key1', ColumnPath('StandardLong1', column=name), 'v', 0, ConsistencyLevel.ONE)
+            client.insert('Keyspace1', 'key1', ColumnParent('StandardLong1'), Column(name, 'v', 0), ConsistencyLevel.ONE)
             L.append(name)
         slice = [result.column.name for result in _big_slice('Keyspace1', 'key1', ColumnParent('StandardLong1'))]
         assert slice == L, slice
@@ -258,7 +258,7 @@ class TestMutations(ThriftTester):
         # 100 isn't enough to fail reliably if the comparator is borked
         for i in xrange(500):
             L.append(uuid.uuid1())
-            client.insert('Keyspace2', 'key1', ColumnPath('Super4', 'sc1', L[-1].bytes), 'value%s' % i, i, ConsistencyLevel.ONE)
+            client.insert('Keyspace2', 'key1', ColumnParent('Super4', 'sc1'), Column(L[-1].bytes, 'value%s' % i, i), ConsistencyLevel.ONE)
         slice = _big_slice('Keyspace2', 'key1', ColumnParent('Super4', 'sc1'))
         assert len(slice) == 500, len(slice)
         for i in xrange(500):
@@ -299,14 +299,14 @@ class TestMutations(ThriftTester):
         sp = SlicePredicate(slice_range=SliceRange('', '', False, 1))
 
         for i in xrange(10):
-            path = ColumnPath('StandardLong1', column=_i64(i))
+            parent = ColumnParent('StandardLong1')
 
-            client.insert('Keyspace1', 'key1', path, 'value1', 10 * i, ConsistencyLevel.ONE)
+            client.insert('Keyspace1', 'key1', parent, Column(_i64(i), 'value1', 10 * i), ConsistencyLevel.ONE)
             client.remove('Keyspace1', 'key1', ColumnPath('StandardLong1'), 10 * i + 1, ConsistencyLevel.ONE)
             slice = client.get_slice('Keyspace1', 'key1', column_parent, sp, ConsistencyLevel.ONE)
             assert slice == [], slice
             # resurrect
-            client.insert('Keyspace1', 'key1', path, 'value2', 10 * i + 2, ConsistencyLevel.ONE)
+            client.insert('Keyspace1', 'key1', parent, Column(_i64(i), 'value2', 10 * i + 2), ConsistencyLevel.ONE)
             slice = [result.column
                      for result in client.get_slice('Keyspace1', 'key1', column_parent, sp, ConsistencyLevel.ONE)]
             assert slice == [Column(_i64(i), 'value2', 10 * i + 2)], (slice, i)
@@ -495,22 +495,22 @@ class TestMutations(ThriftTester):
         _expect_exception(send_range, InvalidRequestException)
 
     def test_column_name_lengths(self):
-        _expect_exception(lambda: client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column=''), 'value', 0, ConsistencyLevel.ONE), InvalidRequestException)
-        client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='x'*1), 'value', 0, ConsistencyLevel.ONE)
-        client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='x'*127), 'value', 0, ConsistencyLevel.ONE)
-        client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='x'*128), 'value', 0, ConsistencyLevel.ONE)
-        client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='x'*129), 'value', 0, ConsistencyLevel.ONE)
-        client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='x'*255), 'value', 0, ConsistencyLevel.ONE)
-        client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='x'*256), 'value', 0, ConsistencyLevel.ONE)
-        client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='x'*257), 'value', 0, ConsistencyLevel.ONE)
-        client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='x'*(2**16 - 1)), 'value', 0, ConsistencyLevel.ONE)
-        _expect_exception(lambda: client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='x'*(2**16)), 'value', 0, ConsistencyLevel.ONE), InvalidRequestException)
+        _expect_exception(lambda: client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('', 'value', 0), ConsistencyLevel.ONE), InvalidRequestException)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('x'*1, 'value', 0), ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('x'*127, 'value', 0), ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('x'*128, 'value', 0), ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('x'*129, 'value', 0), ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('x'*255, 'value', 0), ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('x'*256, 'value', 0), ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('x'*257, 'value', 0), ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('x'*(2**16 - 1), 'value', 0), ConsistencyLevel.ONE)
+        _expect_exception(lambda: client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('x'*(2**16), 'value', 0), ConsistencyLevel.ONE), InvalidRequestException)
 
     def test_bad_calls(self):
         # missing arguments
-        _expect_exception(lambda: client.insert(None, None, None, None, None, None), TApplicationException)
+        _expect_exception(lambda: client.insert(None, None, None, None, None), TApplicationException)
         # supercolumn in a non-super CF
-        _expect_exception(lambda: client.insert('Keyspace1', 'key1', ColumnPath('Standard1', 'x', 'y'), 'value', 0, ConsistencyLevel.ONE), InvalidRequestException)
+        _expect_exception(lambda: client.insert('Keyspace1', 'key1', ColumnParent('Standard1', 'x'), Column('y', 'value', 0), ConsistencyLevel.ONE), InvalidRequestException)
         # key too long
         _expect_exception(lambda: client.get('Keyspace1', 'x' * 2**16, ColumnPath('Standard1', column='c1'), ConsistencyLevel.ONE), InvalidRequestException)
         # empty key
@@ -529,7 +529,7 @@ class TestMutations(ThriftTester):
         # invalid CF
         _expect_exception(lambda: client.get_range_slice('Keyspace1', ColumnParent('S'), SlicePredicate(column_names=['', '']), '', '', 5, ConsistencyLevel.ONE), InvalidRequestException)
         # 'x' is not a valid Long
-        _expect_exception(lambda: client.insert('Keyspace1', 'key1', ColumnPath('Super1', 'sc1', 'x'), 'value', 0, ConsistencyLevel.ONE), InvalidRequestException)
+        _expect_exception(lambda: client.insert('Keyspace1', 'key1', ColumnParent('Super1', 'sc1'), Column('x', 'value', 0), ConsistencyLevel.ONE), InvalidRequestException)
         # start is not a valid Long
         p = SlicePredicate(slice_range=SliceRange('x', '', False, 1))
         column_parent = ColumnParent('StandardLong1')
@@ -577,19 +577,19 @@ class TestMutations(ThriftTester):
             == [ColumnOrSuperColumn(column=Column('c2', 'value2', 0))]
 
         # New insert, make sure it shows up post-remove:
-        client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='c3'), 'value3', 0, ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('c3', 'value3', 0), ConsistencyLevel.ONE)
         columns = [result.column
                    for result in _big_slice('Keyspace1', 'key1', ColumnParent('Standard1'))]
         assert columns == [Column('c2', 'value2', 0), Column('c3', 'value3', 0)], columns
 
         # Test resurrection.  First, re-insert the value w/ older timestamp, 
         # and make sure it stays removed
-        client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='c1'), 'value1', 0, ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('c1', 'value1', 0), ConsistencyLevel.ONE)
         columns = [result.column
                    for result in _big_slice('Keyspace1', 'key1', ColumnParent('Standard1'))]
         assert columns == [Column('c2', 'value2', 0), Column('c3', 'value3', 0)], columns
         # Next, w/ a newer timestamp; it should come back:
-        client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='c1'), 'value1', 2, ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('c1', 'value1', 2), ConsistencyLevel.ONE)
         columns = [result.column
                    for result in _big_slice('Keyspace1', 'key1', ColumnParent('Standard1'))]
         assert columns == [Column('c1', 'value1', 2), Column('c2', 'value2', 0), Column('c3', 'value3', 0)], columns
@@ -606,10 +606,10 @@ class TestMutations(ThriftTester):
 
         # Test resurrection.  First, re-insert a value w/ older timestamp, 
         # and make sure it stays removed:
-        client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='c1'), 'value1', 0, ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('c1', 'value1', 0), ConsistencyLevel.ONE)
         assert _big_slice('Keyspace1', 'key1', ColumnParent('Standard1')) == []
         # Next, w/ a newer timestamp; it should come back:
-        client.insert('Keyspace1', 'key1', ColumnPath('Standard1', column='c1'), 'value1', 4, ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), Column('c1', 'value1', 4), ConsistencyLevel.ONE)
         result = _big_slice('Keyspace1', 'key1', ColumnParent('Standard1'))
         assert result == [ColumnOrSuperColumn(column=Column('c1', 'value1', 4))], result
 
@@ -632,7 +632,7 @@ class TestMutations(ThriftTester):
         _verify_simple()
 
         # New insert, make sure it shows up post-remove:
-        client.insert('Keyspace1', 'key1', ColumnPath('Super1', 'sc2', _i64(7)), 'value7', 0, ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Super1', 'sc2'), Column(_i64(7), 'value7', 0), ConsistencyLevel.ONE)
         super_columns_expected = [SuperColumn(name='sc1', 
                                               columns=[Column(_i64(4), 'value4', 0)]),
                                   SuperColumn(name='sc2', 
@@ -643,13 +643,13 @@ class TestMutations(ThriftTester):
 
         # Test resurrection.  First, re-insert the value w/ older timestamp, 
         # and make sure it stays removed:
-        client.insert('Keyspace1', 'key1', ColumnPath('Super1', 'sc2', _i64(5)), 'value5', 0, ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Super1', 'sc2'), Column(_i64(5), 'value5', 0), ConsistencyLevel.ONE)
 
         super_columns = [result.super_column for result in _big_slice('Keyspace1', 'key1', ColumnParent('Super1'))]
         assert super_columns == super_columns_expected, super_columns
 
         # Next, w/ a newer timestamp; it should come back
-        client.insert('Keyspace1', 'key1', ColumnPath('Super1', 'sc2', _i64(5)), 'value5', 6, ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Super1', 'sc2'), Column(_i64(5), 'value5', 6), ConsistencyLevel.ONE)
         super_columns = [result.super_column for result in _big_slice('Keyspace1', 'key1', ColumnParent('Super1'))]
         super_columns_expected = [SuperColumn(name='sc1', columns=[Column(_i64(4), 'value4', 0)]), 
                                   SuperColumn(name='sc2', columns=[Column(_i64(5), 'value5', 6), 
@@ -674,13 +674,13 @@ class TestMutations(ThriftTester):
 
         # Test resurrection.  First, re-insert the value w/ older timestamp, 
         # and make sure it stays removed:
-        client.insert('Keyspace1', 'key1', ColumnPath('Super1', 'sc2', _i64(5)), 'value5', 1, ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Super1', 'sc2'), Column(_i64(5), 'value5', 1), ConsistencyLevel.ONE)
         super_columns = [result.super_column
                          for result in _big_slice('Keyspace1', 'key1', ColumnParent('Super1'))]
         assert super_columns == super_columns_expected, super_columns
 
         # Next, w/ a newer timestamp; it should come back
-        client.insert('Keyspace1', 'key1', ColumnPath('Super1', 'sc2', _i64(5)), 'value5', 6, ConsistencyLevel.ONE)
+        client.insert('Keyspace1', 'key1', ColumnParent('Super1', 'sc2'), Column(_i64(5), 'value5', 6), ConsistencyLevel.ONE)
         super_columns = [result.super_column
                          for result in _big_slice('Keyspace1', 'key1', ColumnParent('Super1'))]
         super_columns_expected = [SuperColumn(name='sc1', columns=[Column(_i64(4), 'value4', 0)]),
@@ -696,11 +696,11 @@ class TestMutations(ThriftTester):
 
     def test_super_cf_resurrect_subcolumn(self):
         key = 'vijay'
-        client.insert('Keyspace1', key, ColumnPath('Super1', 'sc1', _i64(4)), 'value4', 0, ConsistencyLevel.ONE)
+        client.insert('Keyspace1', key, ColumnParent('Super1', 'sc1'), Column(_i64(4), 'value4', 0), ConsistencyLevel.ONE)
 
         client.remove('Keyspace1', key, ColumnPath('Super1', 'sc1'), 1, ConsistencyLevel.ONE)
 
-        client.insert('Keyspace1', key, ColumnPath('Super1', 'sc1', _i64(4)), 'value4', 2, ConsistencyLevel.ONE)
+        client.insert('Keyspace1', key, ColumnParent('Super1', 'sc1'), Column(_i64(4), 'value4', 2), ConsistencyLevel.ONE)
 
         result = client.get('Keyspace1', key, ColumnPath('Super1', 'sc1'), ConsistencyLevel.ONE)
         assert result.super_column.columns is not None, result.super_column
@@ -730,7 +730,8 @@ class TestMutations(ThriftTester):
 
     def test_range_collation(self):
         for key in ['-a', '-b', 'a', 'b'] + [str(i) for i in xrange(100)]:
-            client.insert('Keyspace1', key, ColumnPath('Standard1', column=key), 'v', 0, ConsistencyLevel.ONE)
+            client.insert('Keyspace1', key, ColumnParent('Standard1'), Column(key, 'v', 0), ConsistencyLevel.ONE)
+
         slices = client.get_range_slice('Keyspace1', ColumnParent('Standard1'), SlicePredicate(column_names=['-a', '-a']), '', '', 1000, ConsistencyLevel.ONE)
         # note the collated ordering rather than ascii
         L = ['0', '1', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '2', '20', '21', '22', '23', '24', '25', '26', '27','28', '29', '3', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '4', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '5', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '6', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '7', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '8', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '9', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', 'a', '-a', 'b', '-b']
@@ -740,7 +741,8 @@ class TestMutations(ThriftTester):
 
     def test_range_partial(self):
         for key in ['-a', '-b', 'a', 'b'] + [str(i) for i in xrange(100)]:
-            client.insert('Keyspace1', key, ColumnPath('Standard1', column=key), 'v', 0, ConsistencyLevel.ONE)
+            client.insert('Keyspace1', key, ColumnParent('Standard1'), Column(key, 'v', 0), ConsistencyLevel.ONE)
+
         
         def check_slices_against_keys(keyList, sliceList):
             assert len(keyList) == len(sliceList)
@@ -770,7 +772,7 @@ class TestMutations(ThriftTester):
     def test_get_range_slices_tokens(self):
         for key in ['key1', 'key2', 'key3', 'key4', 'key5']:
             for cname in ['col1', 'col2', 'col3', 'col4', 'col5']:
-                client.insert('Keyspace2', key, ColumnPath('Super3', 'sc1', cname), 'v-' + cname, 0, ConsistencyLevel.ONE)
+                client.insert('Keyspace2', key, ColumnParent('Super3', 'sc1'), Column(cname, 'v-' + cname, 0), ConsistencyLevel.ONE)
 
         cp = ColumnParent('Super3', 'sc1')
         predicate = SlicePredicate(column_names=['col1', 'col3'])
@@ -783,7 +785,7 @@ class TestMutations(ThriftTester):
     def test_get_range_slice_super(self):
         for key in ['key1', 'key2', 'key3', 'key4', 'key5']:
             for cname in ['col1', 'col2', 'col3', 'col4', 'col5']:
-                client.insert('Keyspace2', key, ColumnPath('Super3', 'sc1', cname), 'v-' + cname, 0, ConsistencyLevel.ONE)
+                client.insert('Keyspace2', key, ColumnParent('Super3', 'sc1'), Column(cname, 'v-' + cname, 0), ConsistencyLevel.ONE)
 
         cp = ColumnParent('Super3', 'sc1')
         result = client.get_range_slice("Keyspace2", cp, SlicePredicate(column_names=['col1', 'col3']), 'key2', 'key4', 5, ConsistencyLevel.ONE)
@@ -799,7 +801,7 @@ class TestMutations(ThriftTester):
     def test_get_range_slice(self):
         for key in ['key1', 'key2', 'key3', 'key4', 'key5']:
             for cname in ['col1', 'col2', 'col3', 'col4', 'col5']:
-                client.insert('Keyspace1', key, ColumnPath('Standard1', column=cname), 'v-' + cname, 0, ConsistencyLevel.ONE)
+                client.insert('Keyspace1', key, ColumnParent('Standard1'), Column(cname, 'v-' + cname, 0), ConsistencyLevel.ONE)
         cp = ColumnParent('Standard1')
 
         # test empty slice
@@ -912,12 +914,12 @@ class TestMutations(ThriftTester):
 
     def test_super_reinsert(self):
         for x in xrange(3):
-            client.insert('Keyspace1', 'key1', ColumnPath('Super1', 'sc2', _i64(x)), 'value', 1, ConsistencyLevel.ONE)
+            client.insert('Keyspace1', 'key1', ColumnParent('Super1', 'sc2'), Column(_i64(x), 'value', 1), ConsistencyLevel.ONE)
 
         client.remove('Keyspace1', 'key1', ColumnPath('Super1'), 2, ConsistencyLevel.ONE)
 
         for x in xrange(3):
-            client.insert('Keyspace1', 'key1', ColumnPath('Super1', 'sc2', _i64(x + 3)), 'value', 3, ConsistencyLevel.ONE)
+            client.insert('Keyspace1', 'key1', ColumnParent('Super1', 'sc2'), Column(_i64(x + 3), 'value', 3), ConsistencyLevel.ONE)
 
         for n in xrange(1, 4):
             p =  SlicePredicate(slice_range=SliceRange('', '', False, n))
@@ -985,4 +987,46 @@ class TestMutations(ThriftTester):
         assert 'RenameColumnFamily' not in ks1
         assert 'NewColumnFamily' not in ks1
         assert 'Standard1' in ks1
+
+    def test_insert_ttl(self):
+        """ Test simple insertion of a column with ttl """
+        column = Column('cttl1', 'value1', 0, 5)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), column, ConsistencyLevel.ONE)
+        assert client.get('Keyspace1', 'key1', ColumnPath('Standard1', column='cttl1'), ConsistencyLevel.ONE).column == column
+
+    def test_insert_negative_ttl(self):
+        """ Test insertion of a column with negative (invalid) ttl """
+        column = Column('cttl2', 'value1', 0, -10)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), column, ConsistencyLevel.ONE)
+        time.sleep(0.1)
+        assert client.get('Keyspace1', 'key1', ColumnPath('Standard1', column='cttl2'), ConsistencyLevel.ONE).column == Column('cttl2', 'value1', 0)
+
+    def test_simple_expiration(self):
+        """ Test that column ttled do expires """
+        column = Column('cttl3', 'value1', 0, 2)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), column, ConsistencyLevel.ONE)
+        time.sleep(1)
+        c = client.get('Keyspace1', 'key1', ColumnPath('Standard1', column='cttl3'), ConsistencyLevel.ONE).column
+        print c
+        print column
+        assert c == column
+        #assert client.get('Keyspace1', 'key1', ColumnPath('Standard1', column='cttl3'), ConsistencyLevel.ONE).column == column
+        time.sleep(2)
+        _expect_missing(lambda: client.get('Keyspace1', 'key1', ColumnPath('Standard1', column='cttl3'), ConsistencyLevel.ONE))
+
+    def test_update_expiring(self):
+        """ Test that updating a column with ttl override the ttl """
+        column1 = Column('cttl4', 'value1', 0, 1)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), column1, ConsistencyLevel.ONE)
+        column2 = Column('cttl4', 'value1', 1)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), column2, ConsistencyLevel.ONE)
+        time.sleep(1.5)
+        assert client.get('Keyspace1', 'key1', ColumnPath('Standard1', column='cttl4'), ConsistencyLevel.ONE).column == column2
+
+    def test_remove_expiring(self):
+        """ Test removing a column with ttl """
+        column = Column('cttl5', 'value1', 0, 10)
+        client.insert('Keyspace1', 'key1', ColumnParent('Standard1'), column, ConsistencyLevel.ONE)
+        client.remove('Keyspace1', 'key1', ColumnPath('Standard1', column='cttl5'), 1, ConsistencyLevel.ONE)
+        _expect_missing(lambda: client.get('Keyspace1', 'key1', ColumnPath('Standard1', column='ctt5'), ConsistencyLevel.ONE))
         

Modified: cassandra/trunk/test/unit/org/apache/cassandra/client/TestRingCache.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/client/TestRingCache.java?rev=935088&r1=935087&r2=935088&view=diff
==============================================================================
--- cassandra/trunk/test/unit/org/apache/cassandra/client/TestRingCache.java (original)
+++ cassandra/trunk/test/unit/org/apache/cassandra/client/TestRingCache.java Fri Apr 16 22:04:46 2010
@@ -24,6 +24,7 @@ import java.util.List;
 import org.apache.cassandra.thrift.Cassandra;
 import org.apache.cassandra.thrift.Column;
 import org.apache.cassandra.thrift.ColumnPath;
+import org.apache.cassandra.thrift.ColumnParent;
 import org.apache.cassandra.thrift.ConsistencyLevel;
 
 import org.apache.cassandra.config.DatabaseDescriptor;
@@ -89,6 +90,7 @@ public class TestRingCache
         {
             byte[] row = (rowPrefix + nRows).getBytes();
             ColumnPath col = new ColumnPath("Standard1").setSuper_column(null).setColumn("col1".getBytes());
+            ColumnParent parent = new ColumnParent("Standard1").setSuper_column(null);
 
             List<InetAddress> endPoints = tester.ringCache.getEndPoint(row);
             String hosts="";
@@ -98,7 +100,7 @@ public class TestRingCache
 
             // now, read the row back directly from the host owning the row locally
             tester.setup(endPoints.get(0).getHostAddress(), DatabaseDescriptor.getRpcPort());
-            tester.thriftClient.insert(keyspace, row, col, "val1".getBytes(), 1, ConsistencyLevel.ONE);
+            tester.thriftClient.insert(keyspace, row, parent, new Column("col1".getBytes(), "val1".getBytes(), 1), ConsistencyLevel.ONE);
             Column column = tester.thriftClient.get(keyspace, row, col, ConsistencyLevel.ONE).column;
             System.out.println("read row " + new String(row) + " " + new String(column.name) + ":" + new String(column.value) + ":" + column.timestamp);
         }

Modified: cassandra/trunk/test/unit/org/apache/cassandra/service/EmbeddedCassandraServiceTest.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/service/EmbeddedCassandraServiceTest.java?rev=935088&r1=935087&r2=935088&view=diff
==============================================================================
--- cassandra/trunk/test/unit/org/apache/cassandra/service/EmbeddedCassandraServiceTest.java (original)
+++ cassandra/trunk/test/unit/org/apache/cassandra/service/EmbeddedCassandraServiceTest.java Fri Apr 16 22:04:46 2010
@@ -28,8 +28,12 @@ import org.apache.cassandra.config.Confi
 import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.config.KSMetaData;
 import org.apache.cassandra.thrift.Cassandra;
+import org.apache.cassandra.thrift.Column;
 import org.apache.cassandra.thrift.ColumnOrSuperColumn;
+import org.apache.cassandra.thrift.Column;
+import org.apache.cassandra.thrift.ColumnParent;
 import org.apache.cassandra.thrift.ColumnPath;
+import org.apache.cassandra.thrift.ColumnParent;
 import org.apache.cassandra.thrift.ConsistencyLevel;
 import org.apache.cassandra.thrift.InvalidRequestException;
 import org.apache.cassandra.thrift.NotFoundException;
@@ -93,11 +97,12 @@ public class EmbeddedCassandraServiceTes
 
         long timestamp = System.currentTimeMillis();
         ColumnPath cp = new ColumnPath("Standard1");
+        ColumnParent par = new ColumnParent("Standard1");
         cp.setColumn("name".getBytes("utf-8"));
 
         // insert
-        client.insert("Keyspace1", key_user_id, cp, "Ran".getBytes("UTF-8"),
-                timestamp, ConsistencyLevel.ONE);
+        client.insert("Keyspace1", key_user_id, par, 
+                new Column("name".getBytes("utf-8"), "Ran".getBytes("UTF-8"), timestamp), ConsistencyLevel.ONE);
 
         // read
         ColumnOrSuperColumn got = client.get("Keyspace1", key_user_id, cp,



Mime
View raw message