Return-Path: X-Original-To: apmail-cassandra-commits-archive@www.apache.org Delivered-To: apmail-cassandra-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 20D8B181FB for ; Wed, 17 Feb 2016 10:57:18 +0000 (UTC) Received: (qmail 53172 invoked by uid 500); 17 Feb 2016 10:57:18 -0000 Delivered-To: apmail-cassandra-commits-archive@cassandra.apache.org Received: (qmail 53141 invoked by uid 500); 17 Feb 2016 10:57:18 -0000 Mailing-List: contact commits-help@cassandra.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@cassandra.apache.org Delivered-To: mailing list commits@cassandra.apache.org Received: (qmail 53130 invoked by uid 99); 17 Feb 2016 10:57:17 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Wed, 17 Feb 2016 10:57:17 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id C73F3E020D; Wed, 17 Feb 2016 10:57:17 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: blerer@apache.org To: commits@cassandra.apache.org Date: Wed, 17 Feb 2016 10:57:17 -0000 Message-Id: <39721c5beacf4ef28338cc53d3c93083@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [1/2] cassandra git commit: Disallow drop/alter operations of UDTs used by UDAs Repository: cassandra Updated Branches: refs/heads/trunk 09fd433cb -> 0d8e853d9 Disallow drop/alter operations of UDTs used by UDAs patch by Robert Stupp; reviewed by Benjamin Lerer for CASSANDRA-10721 Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/7a3c3abe Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/7a3c3abe Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/7a3c3abe Branch: refs/heads/trunk Commit: 7a3c3abe1d1a191f06f99f989c940a5f8ce52f5f Parents: 931d2e5 Author: Robert Stupp Authored: Wed Feb 17 11:48:38 2016 +0100 Committer: Benjamin Lerer Committed: Wed Feb 17 11:53:38 2016 +0100 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../cql3/statements/AlterTypeStatement.java | 28 +++++--- .../cql3/statements/DropTypeStatement.java | 40 ++---------- .../db/marshal/AbstractCompositeType.java | 6 ++ .../cassandra/db/marshal/AbstractType.java | 7 +- .../cassandra/db/marshal/CompositeType.java | 11 ---- .../apache/cassandra/db/marshal/ListType.java | 4 +- .../apache/cassandra/db/marshal/MapType.java | 5 +- .../cassandra/db/marshal/ReversedType.java | 4 +- .../apache/cassandra/db/marshal/SetType.java | 4 +- .../apache/cassandra/db/marshal/TupleType.java | 9 +-- .../apache/cassandra/db/marshal/UserType.java | 9 ++- .../cql3/validation/entities/UserTypesTest.java | 68 ++++++++++++++++++++ .../commitlog/CommitLogSegmentManagerTest.java | 63 ++++++++++++++++++ 14 files changed, 182 insertions(+), 77 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/7a3c3abe/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index 32c165b..f1a9719 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.0.4 + * Disallow drop/alter operations of UDTs used by UDAs (CASSANDRA-10721) * Add query time validation method on Index (CASSANDRA-11043) * Avoid potential AssertionError in mixed version cluster (CASSANDRA-11128) * Properly handle hinted handoff after topology changes (CASSANDRA-5902) http://git-wip-us.apache.org/repos/asf/cassandra/blob/7a3c3abe/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java b/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java index 068b996..8e51c26 100644 --- a/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java @@ -36,7 +36,6 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement protected AlterTypeStatement(UTName name) { - super(); this.name = name; } @@ -50,7 +49,7 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement throw new InvalidRequestException("You need to be logged in a keyspace or use a fully qualified user type name"); } - protected abstract UserType makeUpdatedType(UserType toUpdate) throws InvalidRequestException; + protected abstract UserType makeUpdatedType(UserType toUpdate, KeyspaceMetadata ksm) throws InvalidRequestException; public static AlterTypeStatement addition(UTName name, ColumnIdentifier fieldName, CQL3Type.Raw type) { @@ -94,7 +93,7 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement ksm.types.get(name.getUserTypeName()) .orElseThrow(() -> new InvalidRequestException(String.format("No user type named %s exists.", name))); - UserType updated = makeUpdatedType(toUpdate); + UserType updated = makeUpdatedType(toUpdate, ksm); // Now, we need to announce the type update to basically change it for new tables using this type, // but we also need to find all existing user types and CF using it and change them. @@ -236,6 +235,15 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement return updatedTypes; } + protected void checkTypeNotUsedByAggregate(KeyspaceMetadata ksm) + { + ksm.functions.udas().filter(aggregate -> aggregate.initialCondition() != null && aggregate.stateType().referencesUserType(name.getStringTypeName())) + .findAny() + .ifPresent((aggregate) -> { + throw new InvalidRequestException(String.format("Cannot alter user type %s as it is still used as an INITCOND by aggregate %s", name, aggregate)); + }); + } + private static class AddOrAlter extends AlterTypeStatement { private final boolean isAdd; @@ -260,7 +268,7 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement newNames.add(fieldName.bytes); AbstractType addType = type.prepare(keyspace()).getType(); - if (addType.references(toUpdate)) + if (addType.referencesUserType(toUpdate.getNameAsString())) throw new InvalidRequestException(String.format("Cannot add new field %s of type %s to type %s as this would create a circular reference", fieldName, type, name)); List> newTypes = new ArrayList<>(toUpdate.size() + 1); @@ -270,8 +278,10 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement return new UserType(toUpdate.keyspace, toUpdate.name, newNames, newTypes); } - private UserType doAlter(UserType toUpdate) throws InvalidRequestException + private UserType doAlter(UserType toUpdate, KeyspaceMetadata ksm) throws InvalidRequestException { + checkTypeNotUsedByAggregate(ksm); + int idx = getIdxOfField(toUpdate, fieldName); if (idx < 0) throw new InvalidRequestException(String.format("Unknown field %s in type %s", fieldName, name)); @@ -287,9 +297,9 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement return new UserType(toUpdate.keyspace, toUpdate.name, newNames, newTypes); } - protected UserType makeUpdatedType(UserType toUpdate) throws InvalidRequestException + protected UserType makeUpdatedType(UserType toUpdate, KeyspaceMetadata ksm) throws InvalidRequestException { - return isAdd ? doAdd(toUpdate) : doAlter(toUpdate); + return isAdd ? doAdd(toUpdate) : doAlter(toUpdate, ksm); } } @@ -303,8 +313,10 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement this.renames = renames; } - protected UserType makeUpdatedType(UserType toUpdate) throws InvalidRequestException + protected UserType makeUpdatedType(UserType toUpdate, KeyspaceMetadata ksm) throws InvalidRequestException { + checkTypeNotUsedByAggregate(ksm); + List newNames = new ArrayList<>(toUpdate.fieldNames()); List> newTypes = new ArrayList<>(toUpdate.fieldTypes()); http://git-wip-us.apache.org/repos/asf/cassandra/blob/7a3c3abe/src/java/org/apache/cassandra/cql3/statements/DropTypeStatement.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/cql3/statements/DropTypeStatement.java b/src/java/org/apache/cassandra/cql3/statements/DropTypeStatement.java index 6db47ca..00988af 100644 --- a/src/java/org/apache/cassandra/cql3/statements/DropTypeStatement.java +++ b/src/java/org/apache/cassandra/cql3/statements/DropTypeStatement.java @@ -35,7 +35,6 @@ public class DropTypeStatement extends SchemaAlteringStatement public DropTypeStatement(UTName name, boolean ifExists) { - super(); this.name = name; this.ifExists = ifExists; } @@ -80,55 +79,24 @@ public class DropTypeStatement extends SchemaAlteringStatement for (Function function : ksm.functions) { - if (isUsedBy(function.returnType())) + if (function.returnType().referencesUserType(name.getStringTypeName())) throw new InvalidRequestException(String.format("Cannot drop user type %s as it is still used by function %s", name, function)); for (AbstractType argType : function.argTypes()) - if (isUsedBy(argType)) + if (argType.referencesUserType(name.getStringTypeName())) throw new InvalidRequestException(String.format("Cannot drop user type %s as it is still used by function %s", name, function)); } for (UserType ut : ksm.types) - if (!ut.name.equals(name.getUserTypeName()) && isUsedBy(ut)) + if (!ut.name.equals(name.getUserTypeName()) && ut.referencesUserType(name.getStringTypeName())) throw new InvalidRequestException(String.format("Cannot drop user type %s as it is still used by user type %s", name, ut.getNameAsString())); for (CFMetaData cfm : ksm.tablesAndViews()) for (ColumnDefinition def : cfm.allColumns()) - if (isUsedBy(def.type)) + if (def.type.referencesUserType(name.getStringTypeName())) throw new InvalidRequestException(String.format("Cannot drop user type %s as it is still used by table %s.%s", name, cfm.ksName, cfm.cfName)); } - private boolean isUsedBy(AbstractType toCheck) throws RequestValidationException - { - if (toCheck instanceof UserType) - { - UserType ut = (UserType)toCheck; - if (name.getKeyspace().equals(ut.keyspace) && name.getUserTypeName().equals(ut.name)) - return true; - - for (AbstractType subtype : ut.fieldTypes()) - if (isUsedBy(subtype)) - return true; - } - else if (toCheck instanceof CompositeType) - { - CompositeType ct = (CompositeType)toCheck; - for (AbstractType subtype : ct.types) - if (isUsedBy(subtype)) - return true; - } - else if (toCheck instanceof CollectionType) - { - if (toCheck instanceof ListType) - return isUsedBy(((ListType)toCheck).getElementsType()); - else if (toCheck instanceof SetType) - return isUsedBy(((SetType)toCheck).getElementsType()); - else - return isUsedBy(((MapType)toCheck).getKeysType()) || isUsedBy(((MapType)toCheck).getValuesType()); - } - return false; - } - @Override public String keyspace() { http://git-wip-us.apache.org/repos/asf/cassandra/blob/7a3c3abe/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java b/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java index ad4050d..b0d6a5d 100644 --- a/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java +++ b/src/java/org/apache/cassandra/db/marshal/AbstractCompositeType.java @@ -291,6 +291,12 @@ public abstract class AbstractCompositeType extends AbstractType return BytesSerializer.instance; } + @Override + public boolean referencesUserType(String name) + { + return getComponents().stream().anyMatch(f -> f.referencesUserType(name)); + } + /** * @return the comparator for the given component. static CompositeType will consult * @param i DynamicCompositeType will read the type information from @param bb http://git-wip-us.apache.org/repos/asf/cassandra/blob/7a3c3abe/src/java/org/apache/cassandra/db/marshal/AbstractType.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/marshal/AbstractType.java b/src/java/org/apache/cassandra/db/marshal/AbstractType.java index 0253ac6..331f1a4 100644 --- a/src/java/org/apache/cassandra/db/marshal/AbstractType.java +++ b/src/java/org/apache/cassandra/db/marshal/AbstractType.java @@ -400,12 +400,9 @@ public abstract class AbstractType implements Comparator ByteBufferUtil.skipWithVIntLength(in); } - /** - * Checks whether this type or any of the types this type contains references the given type. - */ - public boolean references(AbstractType check) + public boolean referencesUserType(String userTypeName) { - return this.equals(check); + return false; } /** http://git-wip-us.apache.org/repos/asf/cassandra/blob/7a3c3abe/src/java/org/apache/cassandra/db/marshal/CompositeType.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/marshal/CompositeType.java b/src/java/org/apache/cassandra/db/marshal/CompositeType.java index 126307b..d005fd7 100644 --- a/src/java/org/apache/cassandra/db/marshal/CompositeType.java +++ b/src/java/org/apache/cassandra/db/marshal/CompositeType.java @@ -120,17 +120,6 @@ public class CompositeType extends AbstractCompositeType this.types = ImmutableList.copyOf(types); } - @Override - public boolean references(AbstractType check) - { - if (super.references(check)) - return true; - for (AbstractType type : types) - if (type.references(check)) - return true; - return false; - } - protected AbstractType getComparator(int i, ByteBuffer bb) { try http://git-wip-us.apache.org/repos/asf/cassandra/blob/7a3c3abe/src/java/org/apache/cassandra/db/marshal/ListType.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/marshal/ListType.java b/src/java/org/apache/cassandra/db/marshal/ListType.java index 962925b..4480dcb 100644 --- a/src/java/org/apache/cassandra/db/marshal/ListType.java +++ b/src/java/org/apache/cassandra/db/marshal/ListType.java @@ -75,9 +75,9 @@ public class ListType extends CollectionType> } @Override - public boolean references(AbstractType check) + public boolean referencesUserType(String userTypeName) { - return super.references(check) || elements.references(check); + return getElementsType().referencesUserType(userTypeName); } public AbstractType getElementsType() http://git-wip-us.apache.org/repos/asf/cassandra/blob/7a3c3abe/src/java/org/apache/cassandra/db/marshal/MapType.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/marshal/MapType.java b/src/java/org/apache/cassandra/db/marshal/MapType.java index c8a42f4..425ffc2 100644 --- a/src/java/org/apache/cassandra/db/marshal/MapType.java +++ b/src/java/org/apache/cassandra/db/marshal/MapType.java @@ -75,9 +75,10 @@ public class MapType extends CollectionType> } @Override - public boolean references(AbstractType check) + public boolean referencesUserType(String userTypeName) { - return super.references(check) || keys.references(check) || values.references(check); + return getKeysType().referencesUserType(userTypeName) || + getValuesType().referencesUserType(userTypeName); } public AbstractType getKeysType() http://git-wip-us.apache.org/repos/asf/cassandra/blob/7a3c3abe/src/java/org/apache/cassandra/db/marshal/ReversedType.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/marshal/ReversedType.java b/src/java/org/apache/cassandra/db/marshal/ReversedType.java index 4f1f7a2..02320c7 100644 --- a/src/java/org/apache/cassandra/db/marshal/ReversedType.java +++ b/src/java/org/apache/cassandra/db/marshal/ReversedType.java @@ -135,9 +135,9 @@ public class ReversedType extends AbstractType return baseType.getSerializer(); } - public boolean references(AbstractType check) + public boolean referencesUserType(String userTypeName) { - return super.references(check) || baseType.references(check); + return baseType.referencesUserType(userTypeName); } @Override http://git-wip-us.apache.org/repos/asf/cassandra/blob/7a3c3abe/src/java/org/apache/cassandra/db/marshal/SetType.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/marshal/SetType.java b/src/java/org/apache/cassandra/db/marshal/SetType.java index 8c041af..22577b3 100644 --- a/src/java/org/apache/cassandra/db/marshal/SetType.java +++ b/src/java/org/apache/cassandra/db/marshal/SetType.java @@ -69,9 +69,9 @@ public class SetType extends CollectionType> } @Override - public boolean references(AbstractType check) + public boolean referencesUserType(String userTypeName) { - return super.references(check) || elements.references(check); + return getElementsType().referencesUserType(userTypeName); } public AbstractType getElementsType() http://git-wip-us.apache.org/repos/asf/cassandra/blob/7a3c3abe/src/java/org/apache/cassandra/db/marshal/TupleType.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/marshal/TupleType.java b/src/java/org/apache/cassandra/db/marshal/TupleType.java index 9480229..5486183 100644 --- a/src/java/org/apache/cassandra/db/marshal/TupleType.java +++ b/src/java/org/apache/cassandra/db/marshal/TupleType.java @@ -56,14 +56,9 @@ public class TupleType extends AbstractType } @Override - public boolean references(AbstractType check) + public boolean referencesUserType(String name) { - if (super.references(check)) - return true; - for (AbstractType type : types) - if (type.references(check)) - return true; - return false; + return allTypes().stream().anyMatch(f -> f.referencesUserType(name)); } public AbstractType type(int i) http://git-wip-us.apache.org/repos/asf/cassandra/blob/7a3c3abe/src/java/org/apache/cassandra/db/marshal/UserType.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/marshal/UserType.java b/src/java/org/apache/cassandra/db/marshal/UserType.java index 40a35b5..02c9f05 100644 --- a/src/java/org/apache/cassandra/db/marshal/UserType.java +++ b/src/java/org/apache/cassandra/db/marshal/UserType.java @@ -19,7 +19,6 @@ package org.apache.cassandra.db.marshal; import java.nio.ByteBuffer; import java.nio.charset.CharacterCodingException; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.*; @@ -29,7 +28,6 @@ import org.apache.cassandra.cql3.*; import org.apache.cassandra.exceptions.ConfigurationException; import org.apache.cassandra.exceptions.SyntaxException; import org.apache.cassandra.serializers.*; -import org.apache.cassandra.transport.Server; import org.apache.cassandra.utils.ByteBufferUtil; import org.apache.cassandra.utils.Pair; @@ -241,6 +239,13 @@ public class UserType extends TupleType } @Override + public boolean referencesUserType(String userTypeName) + { + return getNameAsString().equals(userTypeName) || + fieldTypes().stream().anyMatch(f -> f.referencesUserType(userTypeName)); + } + + @Override public String toString() { return getClass().getName() + TypeParser.stringifyUserTypeParameters(keyspace, name, fieldNames, types); http://git-wip-us.apache.org/repos/asf/cassandra/blob/7a3c3abe/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java index 0fe4488..d9df206 100644 --- a/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java +++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UserTypesTest.java @@ -447,6 +447,74 @@ public class UserTypesTest extends CQLTester assertInvalidMessage("would create a circular reference", "ALTER TYPE " + typeWithKs(type1) + " ADD needs_to_fail frozen>"); } + @Test + public void testTypeAlterUsedInFunction() throws Throwable + { + String type1 = createType("CREATE TYPE %s (foo ascii)"); + assertComplexInvalidAlterDropStatements(type1, type1, "{foo: 'abc'}"); + + type1 = createType("CREATE TYPE %s (foo ascii)"); + assertComplexInvalidAlterDropStatements(type1, "list>", "[{foo: 'abc'}]"); + + type1 = createType("CREATE TYPE %s (foo ascii)"); + assertComplexInvalidAlterDropStatements(type1, "set>", "{{foo: 'abc'}}"); + + type1 = createType("CREATE TYPE %s (foo ascii)"); + assertComplexInvalidAlterDropStatements(type1, "map>", "{'key': {foo: 'abc'}}"); + + type1 = createType("CREATE TYPE %s (foo ascii)"); + String type2 = createType("CREATE TYPE %s (foo frozen<" + type1 + ">)"); + assertComplexInvalidAlterDropStatements(type1, type2, "{foo: 'abc'}"); + + type1 = createType("CREATE TYPE %s (foo ascii)"); + type2 = createType("CREATE TYPE %s (foo frozen<" + type1 + ">)"); + assertComplexInvalidAlterDropStatements(type1, + "list>", + "[{foo: 'abc'}]"); + + type1 = createType("CREATE TYPE %s (foo ascii)"); + type2 = createType("CREATE TYPE %s (foo frozen>)"); + assertComplexInvalidAlterDropStatements(type1, + "map>", + "{'key': {foo: {{foo: 'abc'}}}}"); + + type1 = createType("CREATE TYPE %s (foo ascii)"); + assertComplexInvalidAlterDropStatements(type1, + "tuple>", + "('key', {foo: 'abc'})"); + + type1 = createType("CREATE TYPE %s (foo ascii)"); + assertComplexInvalidAlterDropStatements(type1, + "tuple, int>>>", + "('key', (({foo: 'abc'}, 0), 0))"); + + type1 = createType("CREATE TYPE %s (foo ascii)"); + type2 = createType("CREATE TYPE %s (foo frozen>)"); + assertComplexInvalidAlterDropStatements(type1, + "tuple>", + "('key', {foo: {{foo: 'abc'}}})"); + } + + private void assertComplexInvalidAlterDropStatements(String type1, String fArgType, String initcond) throws Throwable + { + String f = createFunction(KEYSPACE, type1, "CREATE FUNCTION %s(arg " + fArgType + ", col int) " + + "RETURNS NULL ON NULL INPUT " + + "RETURNS " + fArgType + ' ' + + "LANGUAGE java AS 'return arg;'"); + createAggregate(KEYSPACE, "int", "CREATE AGGREGATE %s(int) " + + "SFUNC " + shortFunctionName(f) + ' ' + + "STYPE " + fArgType + ' ' + + "INITCOND " + initcond); + assertInvalidAlterDropStatements(type1); + } + + private void assertInvalidAlterDropStatements(String t) throws Throwable + { + assertInvalidMessage("Cannot alter user type " + typeWithKs(t), "ALTER TYPE " + typeWithKs(t) + " RENAME foo TO bar;"); + assertInvalidMessage("Cannot alter user type " + typeWithKs(t), "ALTER TYPE " + typeWithKs(t) + " ALTER foo TYPE text;"); + assertInvalidMessage("Cannot drop user type " + typeWithKs(t), "DROP TYPE " + typeWithKs(t) + ';'); + } + private String typeWithKs(String type1) { return keyspace() + '.' + type1; http://git-wip-us.apache.org/repos/asf/cassandra/blob/7a3c3abe/test/unit/org/apache/cassandra/db/commitlog/CommitLogSegmentManagerTest.java ---------------------------------------------------------------------- diff --git a/test/unit/org/apache/cassandra/db/commitlog/CommitLogSegmentManagerTest.java b/test/unit/org/apache/cassandra/db/commitlog/CommitLogSegmentManagerTest.java new file mode 100644 index 0000000..59b380f --- /dev/null +++ b/test/unit/org/apache/cassandra/db/commitlog/CommitLogSegmentManagerTest.java @@ -0,0 +1,63 @@ +package org.apache.cassandra.db.commitlog; + +import java.nio.ByteBuffer; +import java.util.Random; + +import javax.naming.ConfigurationException; + +import org.apache.cassandra.SchemaLoader; +import org.apache.cassandra.config.Config.CommitLogSync; +import org.apache.cassandra.config.DatabaseDescriptor; +import org.apache.cassandra.config.ParameterizedClass; +import org.apache.cassandra.db.ColumnFamilyStore; +import org.apache.cassandra.db.Keyspace; +import org.apache.cassandra.db.Mutation; +import org.apache.cassandra.db.RowUpdateBuilder; +import org.apache.cassandra.db.compaction.CompactionManager; +import org.apache.cassandra.db.marshal.AsciiType; +import org.apache.cassandra.db.marshal.BytesType; +import org.apache.cassandra.schema.KeyspaceParams; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.google.common.collect.ImmutableMap; + +public class CommitLogSegmentManagerTest +{ + private static final String KEYSPACE1 = "CommitLogTest"; + private static final String STANDARD1 = "Standard1"; + private static final String STANDARD2 = "Standard2"; + + private final static byte[] entropy = new byte[1024 * 256]; + @BeforeClass + public static void defineSchema() throws ConfigurationException + { + new Random().nextBytes(entropy); + DatabaseDescriptor.setCommitLogCompression(new ParameterizedClass("LZ4Compressor", ImmutableMap.of())); + DatabaseDescriptor.setCommitLogSegmentSize(1); + DatabaseDescriptor.setCommitLogSync(CommitLogSync.periodic); + DatabaseDescriptor.setCommitLogSyncPeriod(10 * 1000); + SchemaLoader.prepareServer(); + SchemaLoader.createKeyspace(KEYSPACE1, + KeyspaceParams.simple(1), + SchemaLoader.standardCFMD(KEYSPACE1, STANDARD1, 0, AsciiType.instance, BytesType.instance), + SchemaLoader.standardCFMD(KEYSPACE1, STANDARD2, 0, AsciiType.instance, BytesType.instance)); + + CompactionManager.instance.disableAutoCompaction(); + } + + @Test + public void testCompressedCommitLogBackpressure() throws Throwable + { + CommitLog.instance.resetUnsafe(true); + ColumnFamilyStore cfs1 = Keyspace.open(KEYSPACE1).getColumnFamilyStore(STANDARD1); + + Mutation m = new RowUpdateBuilder(cfs1.metadata, 0, "k") + .clustering("bytes") + .add("val", ByteBuffer.wrap(entropy)) + .build(); + + for (int i = 0; i < 20000; i++) + CommitLog.instance.add(m); + } +}