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=1089517&r1=1089516&r2=1089517&view=diff ============================================================================== --- cassandra/trunk/src/java/org/apache/cassandra/thrift/ThriftValidation.java (original) +++ cassandra/trunk/src/java/org/apache/cassandra/thrift/ThriftValidation.java Wed Apr 6 16:19:55 2011 @@ -81,13 +81,7 @@ public class ThriftValidation public static CFMetaData validateColumnFamily(String tablename, String cfName, boolean isCommutativeOp) throws InvalidRequestException { - validateTable(tablename); - if (cfName.isEmpty()) - throw new InvalidRequestException("non-empty columnfamily is required"); - - CFMetaData metadata = DatabaseDescriptor.getCFMetaData(tablename, cfName); - if (metadata == null) - throw new InvalidRequestException("unconfigured columnfamily " + cfName); + CFMetaData metadata = validateColumnFamily(tablename, cfName); if (isCommutativeOp) { @@ -102,6 +96,20 @@ public class ThriftValidation return metadata; } + // This should only be used when the operation should be authorized whether this is a counter CF or not + public static CFMetaData validateColumnFamily(String tablename, String cfName) throws InvalidRequestException + { + validateTable(tablename); + if (cfName.isEmpty()) + throw new InvalidRequestException("non-empty columnfamily is required"); + + CFMetaData metadata = DatabaseDescriptor.getCFMetaData(tablename, cfName); + if (metadata == null) + throw new InvalidRequestException("unconfigured columnfamily " + cfName); + + return metadata; + } + /** * validates all parts of the path to the column, including the column name */ @@ -261,6 +269,22 @@ public class ThriftValidation throw new InvalidRequestException("ColumnOrSuperColumn must have one or both of Column or SuperColumn"); } + public static void validateCounter(CFMetaData metadata, Counter counter) + throws InvalidRequestException + { + if (counter.column != null) + validateColumnPath(metadata, new ColumnPath(metadata.cfName).setSuper_column((ByteBuffer)null).setColumn(counter.column.name)); + + if (counter.super_column != null) + { + for (CounterColumn c : counter.super_column.columns) + validateColumnPath(metadata, new ColumnPath(metadata.cfName).setSuper_column(counter.super_column.name).setColumn(c.name)); + } + + if (counter.column == null && counter.super_column == null) + throw new InvalidRequestException("Counter must have one or both of column or super_column"); + } + private static void validateTtl(Column column) throws InvalidRequestException { if (column.isSetTtl() && column.ttl <= 0) @@ -276,21 +300,32 @@ public class ThriftValidation { ColumnOrSuperColumn cosc = mut.column_or_supercolumn; Deletion del = mut.deletion; + Counter counter = mut.counter; + + boolean isCommutative = metadata.getDefaultValidator().isCommutative(); - if (cosc != null && del != null) - throw new InvalidRequestException("Mutation may have either a ColumnOrSuperColumn or a Deletion, but not both"); + if (cosc == null && del == null && counter == null) + { + throw new InvalidRequestException("Mutation must have at least one of column_or_superColumn, deletion, counter or counter_deletion"); + } if (cosc != null) { + if (isCommutative) + throw new InvalidRequestException("invalid operation for commutative columnfamily " + metadata.cfName); + validateColumnOrSuperColumn(metadata, cosc); } - else if (del != null) + if (counter != null) { - validateDeletion(metadata, del); + if (!isCommutative) + throw new InvalidRequestException("invalid operation for non commutative columnfamily " + metadata.cfName); + + validateCounter(metadata, counter); } - else + if (del != null) { - throw new InvalidRequestException("Mutation must have one ColumnOrSuperColumn or one Deletion"); + validateDeletion(metadata, del); } } @@ -305,9 +340,19 @@ public class ThriftValidation if (metadata.cfType == ColumnFamilyType.Standard && del.super_column != null) { - String msg = String.format("deletion of super_column is not possible on a standard ColumnFamily (KeySpace=%s ColumnFamily=%s Deletion=%s)", metadata.ksName, metadata.cfName, del); + String msg = String.format("Deletion of super columns is not possible on a standard ColumnFamily (KeySpace=%s ColumnFamily=%s Deletion=%s)", metadata.ksName, metadata.cfName, del); throw new InvalidRequestException(msg); } + + if (metadata.getDefaultValidator().isCommutative()) + { + // forcing server timestamp even if a timestamp was set for coherence with other counter operation + del.timestamp = System.currentTimeMillis(); + } + else if (!del.isSetTimestamp()) + { + throw new InvalidRequestException("Deletion timestamp is not optional for non commutative column family " + metadata.cfName); + } } public static void validateSlicePredicate(CFMetaData metadata, ByteBuffer scName, SlicePredicate predicate) throws InvalidRequestException
Modified: cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceCounterTest.java URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceCounterTest.java?rev=1089517&r1=1089516&r2=1089517&view=diff ============================================================================== --- cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceCounterTest.java (original) +++ cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceCounterTest.java Wed Apr 6 16:19:55 2011 @@ -20,6 +20,12 @@ package org.apache.cassandra.service; * */ +import java.util.List; +import java.util.LinkedList; + +import org.apache.cassandra.db.*; +import org.apache.cassandra.db.filter.QueryPath; +import org.apache.cassandra.utils.ByteBufferUtil; public class AntiEntropyServiceCounterTest extends AntiEntropyServiceTestAbstract { @@ -28,4 +34,14 @@ public class AntiEntropyServiceCounterTe tablename = "Keyspace5"; cfname = "Counter1"; } + + public List<RowMutation> getWriteData() + { + List<RowMutation> rms = new LinkedList<RowMutation>(); + RowMutation rm; + rm = new RowMutation(tablename, ByteBufferUtil.bytes("key1")); + rm.addCounter(new QueryPath(cfname, null, ByteBufferUtil.bytes("Column1")), 42); + rms.add(rm); + return rms; + } } Modified: cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceStandardTest.java URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceStandardTest.java?rev=1089517&r1=1089516&r2=1089517&view=diff ============================================================================== --- cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceStandardTest.java (original) +++ cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceStandardTest.java Wed Apr 6 16:19:55 2011 @@ -20,6 +20,12 @@ package org.apache.cassandra.service; * */ +import java.util.List; +import java.util.LinkedList; + +import org.apache.cassandra.db.*; +import org.apache.cassandra.db.filter.QueryPath; +import org.apache.cassandra.utils.ByteBufferUtil; public class AntiEntropyServiceStandardTest extends AntiEntropyServiceTestAbstract { @@ -28,4 +34,14 @@ public class AntiEntropyServiceStandardT tablename = "Keyspace5"; cfname = "Standard1"; } + + public List<RowMutation> getWriteData() + { + List<RowMutation> rms = new LinkedList<RowMutation>(); + RowMutation rm; + rm = new RowMutation(tablename, ByteBufferUtil.bytes("key1")); + rm.add(new QueryPath(cfname, null, ByteBufferUtil.bytes("Column1")), ByteBufferUtil.bytes("asdfasdf"), 0); + rms.add(rm); + return rms; + } } Modified: cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceTest.java URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceTest.java?rev=1089517&r1=1089516&r2=1089517&view=diff ============================================================================== --- cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceTest.java (original) +++ cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceTest.java Wed Apr 6 16:19:55 2011 @@ -68,8 +68,8 @@ public class AntiEntropyServiceTest exte StorageService.instance.initServer(); // generate a fake endpoint for which we can spoof receiving/sending trees REMOTE = InetAddress.getByName("127.0.0.2"); - store = Table.open(tablename).getColumnFamilyStores().iterator().next(); - cfname = store.columnFamily; + cfname = "Standard1"; + store = Table.open(tablename).getColumnFamilyStore(cfname); } @Before Modified: cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceTestAbstract.java URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceTestAbstract.java?rev=1089517&r1=1089516&r2=1089517&view=diff ============================================================================== --- cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceTestAbstract.java (original) +++ cassandra/trunk/test/unit/org/apache/cassandra/service/AntiEntropyServiceTestAbstract.java Wed Apr 6 16:19:55 2011 @@ -66,6 +66,8 @@ public abstract class AntiEntropyService public abstract void init(); + public abstract List<RowMutation> getWriteData(); + @Before public void prepare() throws Exception { @@ -114,12 +116,7 @@ public abstract class AntiEntropyService Validator validator; // write - List<RowMutation> rms = new LinkedList<RowMutation>(); - RowMutation rm; - rm = new RowMutation(tablename, ByteBufferUtil.bytes("key1")); - rm.add(new QueryPath(cfname, null, ByteBufferUtil.bytes("Column1")), ByteBufferUtil.bytes("asdfasdf"), 0); - rms.add(rm); - Util.writeColumnFamily(rms); + Util.writeColumnFamily(getWriteData()); // sample validator = new Validator(request);
