You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by jb...@apache.org on 2010/07/03 00:11:05 UTC
svn commit: r960123 [2/2] - in /cassandra/trunk: interface/
interface/thrift/gen-java/org/apache/cassandra/thrift/
src/java/org/apache/cassandra/avro/ src/java/org/apache/cassandra/config/
src/java/org/apache/cassandra/db/marshal/ src/java/org/apache/c...
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=960123&r1=960122&r2=960123&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/thrift/ThriftValidation.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/thrift/ThriftValidation.java Fri Jul 2 22:11:04 2010
@@ -20,28 +20,28 @@ package org.apache.cassandra.thrift;
*
*/
-import java.util.Comparator;
import java.util.Arrays;
-import org.apache.commons.lang.ArrayUtils;
+import java.util.Comparator;
-import org.apache.cassandra.db.KeyspaceNotDefinedException;
-import org.apache.cassandra.db.ColumnFamily;
-import org.apache.cassandra.db.IColumn;
-import org.apache.cassandra.db.ColumnFamilyType;
-import org.apache.cassandra.db.IClock;
-import org.apache.cassandra.db.TimestampClock;
-import org.apache.cassandra.db.marshal.AbstractType;
-import org.apache.cassandra.db.marshal.MarshalException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.db.*;
+import org.apache.cassandra.db.marshal.AbstractType;
+import org.apache.cassandra.db.marshal.MarshalException;
import org.apache.cassandra.dht.IPartitioner;
import org.apache.cassandra.dht.RandomPartitioner;
import org.apache.cassandra.dht.Token;
+import org.apache.cassandra.locator.DatacenterShardStrategy;
+import org.apache.cassandra.service.ColumnValidator;
import org.apache.cassandra.service.StorageService;
import org.apache.cassandra.utils.FBUtilities;
public class ThriftValidation
{
+ private static final Logger logger = LoggerFactory.getLogger(DatacenterShardStrategy.class);
+
static void validateKey(byte[] key) throws InvalidRequestException
{
if (key == null || key.length == 0)
@@ -302,10 +302,31 @@ public class ThriftValidation
validateColumns(keyspace, cfName, scName, predicate.column_names);
}
+ public static void runExternalColumnVerifier(String keyspace, ColumnParent column_parent, Column column) throws InvalidRequestException
+ {
+ try
+ {
+ ColumnValidator validator = null;
+ validator = DatabaseDescriptor.getColumnValidator(keyspace, column_parent.column_family, column.name);
+ if (validator != null)
+ validator.validate(keyspace, column_parent, column);
+ }
+ catch (MarshalException me)
+ {
+ String msg = String.format("[%s][%s][md5(byte[])=%s] = [md5(byte[])=%s] failed validation (%s)",
+ keyspace, column_parent.getColumn_family(),
+ FBUtilities.hexHash("MD5", column.name),
+ FBUtilities.hexHash("MD5", column.value),
+ me.getMessage());
+ throw new InvalidRequestException(msg); //why doesn't IRE except a caused_by argument?
+ }
+ }
+
public static void validateColumn(String keyspace, ColumnParent column_parent, Column column) throws InvalidRequestException
{
validateTtl(column);
validateColumns(keyspace, column_parent, Arrays.asList(column.name));
+ runExternalColumnVerifier(keyspace, column_parent, column);
}
public static void validatePredicate(String keyspace, ColumnParent column_parent, SlicePredicate predicate)
Added: cassandra/trunk/src/java/org/apache/cassandra/utils/ByteArrayKey.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/src/java/org/apache/cassandra/utils/ByteArrayKey.java?rev=960123&view=auto
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/utils/ByteArrayKey.java (added)
+++ cassandra/trunk/src/java/org/apache/cassandra/utils/ByteArrayKey.java Fri Jul 2 22:11:04 2010
@@ -0,0 +1,38 @@
+package org.apache.cassandra.utils;
+
+import java.util.Arrays;
+
+/**
+ * A wrapper class for making a byte[] suitable for use as keys (i.e. hashCode/equals)
+ */
+public class ByteArrayKey
+{
+ private final byte[] bytes;
+
+ public ByteArrayKey(byte[] bytes)
+ {
+ this.bytes = bytes;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return Arrays.hashCode(this.bytes);
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == this)
+ {
+ return true;
+ }
+ else if (obj == null || obj.getClass() != getClass())
+ {
+ return false;
+ }
+
+ return Arrays.equals(this.bytes, ((ByteArrayKey) obj).bytes);
+ }
+}
+
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=960123&r1=960122&r2=960123&view=diff
==============================================================================
--- cassandra/trunk/src/java/org/apache/cassandra/utils/FBUtilities.java (original)
+++ cassandra/trunk/src/java/org/apache/cassandra/utils/FBUtilities.java Fri Jul 2 22:11:04 2010
@@ -229,6 +229,11 @@ public class FBUtilities
return hash.abs();
}
+ public static String hexHash(String type, byte[]... data)
+ {
+ return bytesToHex(hash(type, data));
+ }
+
public static byte[] hash(String type, byte[]... data)
{
byte[] result;
Modified: cassandra/trunk/test/system/test_thrift_server.py
URL: http://svn.apache.org/viewvc/cassandra/trunk/test/system/test_thrift_server.py?rev=960123&r1=960122&r2=960123&view=diff
==============================================================================
--- cassandra/trunk/test/system/test_thrift_server.py (original)
+++ cassandra/trunk/test/system/test_thrift_server.py Fri Jul 2 22:11:04 2010
@@ -167,8 +167,8 @@ def _verify_super(supercf='Super1', key=
def _expect_exception(fn, type_):
try:
r = fn()
- except type_:
- pass
+ except type_, t:
+ return t
else:
raise Exception('expected %s; got %s' % (type_.__name__, r))
@@ -1090,11 +1090,45 @@ class TestMutations(ThriftTester):
client.describe_keyspace('RenameKeyspace')
_expect_exception(get_second_ks, NotFoundException)
+ def test_column_validators(self):
+ ks = 'Keyspace1'
+ _set_keyspace(ks)
+ cd = ColumnDef('col', 'org.apache.cassandra.service.ExampleColumnValidator', None, None)
+ cf = CfDef('Keyspace1', 'ValidatorColumnFamily', column_metadata=[cd])
+ client.system_add_column_family(cf)
+ dks = client.describe_keyspace(ks)
+ assert 'ValidatorColumnFamily' in dks
+
+ cp = ColumnParent('ValidatorColumnFamily')
+ col0 = Column('col', 'valuegood', Clock(0))
+ col1 = Column('col', 'valuebad', Clock(0))
+ client.insert('key0', cp, col0, ConsistencyLevel.ONE)
+ e = _expect_exception(lambda: client.insert('key1', cp, col1, ConsistencyLevel.ONE), InvalidRequestException)
+ assert e.why.find("failed validation") >= 0
+ assert e.why.find("column.value.length is even") >= 0
+
+ def test_super_column_validators(self):
+ ks = 'Keyspace1'
+ _set_keyspace(ks)
+ cd = ColumnDef('col', 'org.apache.cassandra.service.ExampleColumnValidator', None, None)
+ cf = CfDef('Keyspace1', 'SuperValidatorColumnFamily', 'Super', column_metadata=[cd])
+ client.system_add_column_family(cf)
+ dks = client.describe_keyspace('Keyspace1')
+ assert 'SuperValidatorColumnFamily' in dks
+
+ cp = ColumnParent('SuperValidatorColumnFamily', 'a subcolumn')
+ col0 = Column('col', 'valuegood', Clock(0))
+ col1 = Column('col', 'valuebad', Clock(0))
+ client.insert('key0', cp, col0, ConsistencyLevel.ONE)
+ e = _expect_exception(lambda: client.insert('key1', cp, col1, ConsistencyLevel.ONE), InvalidRequestException)
+ assert e.why.find("failed validation") >= 0
+ assert e.why.find("column.value.length is even") >= 0
+
def test_system_column_family_operations(self):
- """ Test cf (add, drop, rename) operations """
_set_keyspace('Keyspace1')
# create
- newcf = CfDef('Keyspace1', 'NewColumnFamily')
+ cd = ColumnDef('ValidationColumn', 'randomclass', None, None)
+ newcf = CfDef('Keyspace1', 'NewColumnFamily', column_metadata=[cd])
client.system_add_column_family(newcf)
ks1 = client.describe_keyspace('Keyspace1')
assert 'NewColumnFamily' in ks1
@@ -1113,11 +1147,11 @@ class TestMutations(ThriftTester):
assert 'Standard1' in ks1
def test_system_super_column_family_operations(self):
- """test cf (add, drop, rename) operations"""
_set_keyspace('Keyspace1')
# create
- newcf = CfDef('Keyspace1', 'NewSuperColumnFamily', 'Super')
+ cd = ColumnDef('ValidationColumn', 'randomclass', None, None)
+ newcf = CfDef('Keyspace1', 'NewSuperColumnFamily', 'Super', column_metadata=[cd])
client.system_add_column_family(newcf)
ks1 = client.describe_keyspace('Keyspace1')
assert 'NewSuperColumnFamily' in ks1
@@ -1134,7 +1168,7 @@ class TestMutations(ThriftTester):
assert 'RenameSuperColumnFamily' not in ks1
assert 'NewSuperColumnFamily' not in ks1
assert 'Standard1' in ks1
-
+
def test_insert_ttl(self):
""" Test simple insertion of a column with ttl """
_set_keyspace('Keyspace1')
Modified: cassandra/trunk/test/unit/org/apache/cassandra/db/DefsTest.java
URL: http://svn.apache.org/viewvc/cassandra/trunk/test/unit/org/apache/cassandra/db/DefsTest.java?rev=960123&r1=960122&r2=960123&view=diff
==============================================================================
--- cassandra/trunk/test/unit/org/apache/cassandra/db/DefsTest.java (original)
+++ cassandra/trunk/test/unit/org/apache/cassandra/db/DefsTest.java Fri Jul 2 22:11:04 2010
@@ -17,45 +17,32 @@
*/
package org.apache.cassandra.db;
+import org.apache.cassandra.utils.ByteArrayKey;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.ExecutionException;
+
+import org.junit.Test;
import org.apache.cassandra.CleanupHelper;
import org.apache.cassandra.Util;
-
-import org.apache.cassandra.config.CFMetaData;
-import org.apache.cassandra.config.ConfigurationException;
-import org.apache.cassandra.config.DatabaseDescriptor;
-import org.apache.cassandra.config.KSMetaData;
+import org.apache.cassandra.config.*;
import org.apache.cassandra.db.clock.TimestampReconciler;
import org.apache.cassandra.db.filter.QueryFilter;
import org.apache.cassandra.db.filter.QueryPath;
import org.apache.cassandra.db.marshal.BytesType;
-import org.apache.cassandra.db.migration.AddColumnFamily;
-import org.apache.cassandra.db.migration.AddKeyspace;
-import org.apache.cassandra.db.migration.DropColumnFamily;
-import org.apache.cassandra.db.migration.DropKeyspace;
-import org.apache.cassandra.db.migration.Migration;
-import org.apache.cassandra.db.migration.RenameColumnFamily;
-import org.apache.cassandra.db.migration.RenameKeyspace;
+import org.apache.cassandra.db.marshal.UTF8Type;
+import org.apache.cassandra.db.migration.*;
+import org.apache.cassandra.dht.BytesToken;
import org.apache.cassandra.locator.RackUnawareStrategy;
+import org.apache.cassandra.utils.ByteArrayKey;
import org.apache.cassandra.utils.FBUtilities;
-import org.apache.cassandra.db.marshal.UTF8Type;
import org.apache.cassandra.utils.UUIDGen;
-import org.junit.Test;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import java.util.UUID;
-import java.util.concurrent.ExecutionException;
-
public class DefsTest extends CleanupHelper
{
@Test
@@ -78,7 +65,7 @@ public class DefsTest extends CleanupHel
@Test
public void addNewCfToBogusTable() throws InterruptedException
{
- CFMetaData newCf = new CFMetaData("MadeUpKeyspace", "NewCF", ColumnFamilyType.Standard, ClockType.Timestamp, UTF8Type.instance, null, new TimestampReconciler(), "new cf", 0, false, 1.0, 0);
+ CFMetaData newCf = new CFMetaData("MadeUpKeyspace", "NewCF", ColumnFamilyType.Standard, ClockType.Timestamp, UTF8Type.instance, null, new TimestampReconciler(), "new cf", 0, false, 1.0, 0, Collections.<ByteArrayKey, ColumnDefinition>emptyMap());
try
{
new AddColumnFamily(newCf).apply();
@@ -103,7 +90,7 @@ public class DefsTest extends CleanupHel
assert DatabaseDescriptor.getDefsVersion().equals(prior);
// add a cf.
- CFMetaData newCf1 = new CFMetaData("Keyspace1", "MigrationCf_1", ColumnFamilyType.Standard, ClockType.Timestamp, UTF8Type.instance, null, new TimestampReconciler(), "Migration CF ", 0, false, 1.0, 0);
+ CFMetaData newCf1 = new CFMetaData("Keyspace1", "MigrationCf_1", ColumnFamilyType.Standard, ClockType.Timestamp, UTF8Type.instance, null, new TimestampReconciler(), "Migration CF ", 0, false, 1.0, 0, Collections.<ByteArrayKey, ColumnDefinition>emptyMap());
Migration m1 = new AddColumnFamily(newCf1);
m1.apply();
UUID ver1 = m1.getVersion();
@@ -162,7 +149,7 @@ public class DefsTest extends CleanupHel
final String cf = "BrandNewCf";
KSMetaData original = DatabaseDescriptor.getTableDefinition(ks);
- CFMetaData newCf = new CFMetaData(original.name, cf, ColumnFamilyType.Standard, ClockType.Timestamp, UTF8Type.instance, null, new TimestampReconciler(), "A New Column Family", 0, false, 1.0, 0);
+ CFMetaData newCf = new CFMetaData(original.name, cf, ColumnFamilyType.Standard, ClockType.Timestamp, UTF8Type.instance, null, new TimestampReconciler(), "A New Column Family", 0, false, 1.0, 0, Collections.<ByteArrayKey, ColumnDefinition>emptyMap());
assert !DatabaseDescriptor.getTableDefinition(ks).cfMetaData().containsKey(newCf.cfName);
new AddColumnFamily(newCf).apply();
@@ -185,6 +172,43 @@ public class DefsTest extends CleanupHel
}
@Test
+ public void testCanAddColumnDefinitionsInColumnMetaData() throws Exception
+ {
+ String ks = "Keyspace1";
+ String cf = "ValidatorColumnFamily";
+ KSMetaData original = DatabaseDescriptor.getTableDefinition(ks);
+
+ Map<ByteArrayKey, ColumnDefinition> column_metadata = new HashMap<ByteArrayKey, ColumnDefinition>();
+
+ ColumnDefinition cd0 = new ColumnDefinition();
+ cd0.name = "TestColumn1".getBytes("UTF8");
+ cd0.validation_class = "random class one";
+ cd0.index_name = null;
+ cd0.index_type = null;
+
+ ColumnDefinition cd1 = new ColumnDefinition();
+ cd1.name = "*".getBytes("UTF8");
+ cd1.validation_class = "random class two";
+ cd1.index_name = "some name";
+ cd1.index_type = "some type";
+
+ column_metadata.put(new ByteArrayKey(cd0.name), cd0);
+ column_metadata.put(new ByteArrayKey(cd1.name), cd1);
+
+ CFMetaData newCf = new CFMetaData(original.name, cf, ColumnFamilyType.Standard, ClockType.Timestamp, UTF8Type.instance, null, new TimestampReconciler(), "A New Column Family", 0, false, 1.0, 0, column_metadata);
+ assert !DatabaseDescriptor.getTableDefinition(ks).cfMetaData().containsKey(newCf.cfName);
+ new AddColumnFamily(newCf).apply();
+
+ assert DatabaseDescriptor.getTableDefinition(ks).cfMetaData().containsKey(newCf.cfName);
+ assert DatabaseDescriptor.getTableDefinition(ks).cfMetaData().get(newCf.cfName).equals(newCf);
+
+ ColumnFamilyStore store = Table.open(ks).getColumnFamilyStore(cf);
+ assert store != null;
+ store.forceBlockingFlush();
+ }
+
+
+ @Test
public void dropCf() throws ConfigurationException, IOException, ExecutionException, InterruptedException
{
DecoratedKey dk = Util.dk("dropCf");
@@ -276,7 +300,7 @@ public class DefsTest extends CleanupHel
public void addNewKS() throws ConfigurationException, IOException, ExecutionException, InterruptedException
{
DecoratedKey dk = Util.dk("key0");
- CFMetaData newCf = new CFMetaData("NewKeyspace1", "AddedStandard1", ColumnFamilyType.Standard, ClockType.Timestamp, UTF8Type.instance, null, new TimestampReconciler(), "A new cf for a new ks", 0, false, 1.0, 0);
+ CFMetaData newCf = new CFMetaData("NewKeyspace1", "AddedStandard1", ColumnFamilyType.Standard, ClockType.Timestamp, UTF8Type.instance, null, new TimestampReconciler(), "A new cf for a new ks", 0, false, 1.0, 0, Collections.<ByteArrayKey, ColumnDefinition>emptyMap());
KSMetaData newKs = new KSMetaData(newCf.tableName, RackUnawareStrategy.class, 5, newCf);
new AddKeyspace(newKs).apply();
@@ -432,7 +456,7 @@ public class DefsTest extends CleanupHel
new AddKeyspace(newKs).apply();
assert DatabaseDescriptor.getTableDefinition("EmptyKeyspace") != null;
- CFMetaData newCf = new CFMetaData("EmptyKeyspace", "AddedLater", ColumnFamilyType.Standard, ClockType.Timestamp, UTF8Type.instance, null, new TimestampReconciler(), "A new CF to add to an empty KS", 0, false, 1.0, 0);
+ CFMetaData newCf = new CFMetaData("EmptyKeyspace", "AddedLater", ColumnFamilyType.Standard, ClockType.Timestamp, UTF8Type.instance, null, new TimestampReconciler(), "A new CF to add to an empty KS", 0, false, 1.0, 0, Collections.<ByteArrayKey, ColumnDefinition>emptyMap());
//should not exist until apply
assert !DatabaseDescriptor.getTableDefinition(newKs.name).cfMetaData().containsKey(newCf.cfName);