Repository: cassandra
Updated Branches:
  refs/heads/trunk a827a3717 -> 16044a6f4


Make CFMetaData.triggers immutable

patch by Aleksey Yeschenko; reviewed by Robert Stupp for CASSANDRA-9712


Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo
Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/16044a6f
Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/16044a6f
Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/16044a6f

Branch: refs/heads/trunk
Commit: 16044a6f4c19a899172efc8b2d0ac3e4723d4c88
Parents: a827a37
Author: Aleksey Yeschenko <[email protected]>
Authored: Thu Jul 2 16:46:14 2015 +0300
Committer: Aleksey Yeschenko <[email protected]>
Committed: Fri Jul 10 20:08:59 2015 +0300

----------------------------------------------------------------------
 .../org/apache/cassandra/config/CFMetaData.java |  31 +----
 .../cassandra/config/TriggerDefinition.java     |  69 ----------
 .../cql3/statements/CreateTriggerStatement.java |  22 +--
 .../cql3/statements/DropTriggerStatement.java   |  20 ++-
 .../cassandra/schema/LegacySchemaMigrator.java  |  13 +-
 .../apache/cassandra/schema/SchemaKeyspace.java |  51 ++++---
 .../cassandra/schema/TriggerMetadata.java       |  72 ++++++++++
 .../org/apache/cassandra/schema/Triggers.java   | 137 +++++++++++++++++++
 .../cassandra/thrift/ThriftConversion.java      |  21 +--
 .../cassandra/triggers/TriggerExecutor.java     |   9 +-
 .../cql3/validation/operations/CreateTest.java  |  46 +++----
 .../schema/LegacySchemaMigratorTest.java        |   8 +-
 .../cassandra/triggers/TriggerExecutorTest.java |  24 ++--
 .../cassandra/triggers/TriggersSchemaTest.java  |  26 ++--
 14 files changed, 348 insertions(+), 201 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/16044a6f/src/java/org/apache/cassandra/config/CFMetaData.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java 
b/src/java/org/apache/cassandra/config/CFMetaData.java
index f3c8bc1..53d2171 100644
--- a/src/java/org/apache/cassandra/config/CFMetaData.java
+++ b/src/java/org/apache/cassandra/config/CFMetaData.java
@@ -49,6 +49,7 @@ import org.apache.cassandra.io.compress.CompressionParameters;
 import org.apache.cassandra.io.compress.LZ4Compressor;
 import org.apache.cassandra.io.util.DataOutputPlus;
 import org.apache.cassandra.schema.SchemaKeyspace;
+import org.apache.cassandra.schema.Triggers;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.FBUtilities;
 import org.apache.cassandra.utils.UUIDGen;
@@ -190,8 +191,8 @@ public final class CFMetaData
     private volatile int memtableFlushPeriod = 0;
     private volatile int defaultTimeToLive = DEFAULT_DEFAULT_TIME_TO_LIVE;
     private volatile SpeculativeRetry speculativeRetry = 
DEFAULT_SPECULATIVE_RETRY;
-    private volatile Map<ColumnIdentifier, DroppedColumn> droppedColumns = new 
HashMap();
-    private volatile Map<String, TriggerDefinition> triggers = new HashMap<>();
+    private volatile Map<ColumnIdentifier, DroppedColumn> droppedColumns = new 
HashMap<>();
+    private volatile Triggers triggers = Triggers.none();
     private volatile boolean isPurged = false;
     /*
      * All CQL3 columns definition are stored in the columnMetadata map.
@@ -237,7 +238,7 @@ public final class CFMetaData
     public CFMetaData defaultTimeToLive(int prop) {defaultTimeToLive = prop; 
return this;}
     public CFMetaData speculativeRetry(SpeculativeRetry prop) 
{speculativeRetry = prop; return this;}
     public CFMetaData droppedColumns(Map<ColumnIdentifier, DroppedColumn> 
cols) {droppedColumns = cols; return this;}
-    public CFMetaData triggers(Map<String, TriggerDefinition> prop) {triggers 
= prop; return this;}
+    public CFMetaData triggers(Triggers prop) {triggers = prop; return this;}
 
     private CFMetaData(String keyspace,
                        String name,
@@ -352,7 +353,7 @@ public final class CFMetaData
         return CFMetaData.Builder.create(keyspace, 
name).addPartitionKey("key", BytesType.instance).build();
     }
 
-    public Map<String, TriggerDefinition> getTriggers()
+    public Triggers getTriggers()
     {
         return triggers;
     }
@@ -467,7 +468,7 @@ public final class CFMetaData
                       .speculativeRetry(oldCFMD.speculativeRetry)
                       .memtableFlushPeriod(oldCFMD.memtableFlushPeriod)
                       .droppedColumns(new HashMap<>(oldCFMD.droppedColumns))
-                      .triggers(new HashMap<>(oldCFMD.triggers));
+                      .triggers(oldCFMD.triggers);
     }
 
     /**
@@ -1198,24 +1199,6 @@ public final class CFMetaData
         return removed;
     }
 
-    public void addTriggerDefinition(TriggerDefinition def) throws 
InvalidRequestException
-    {
-        if (containsTriggerDefinition(def))
-            throw new InvalidRequestException(
-                String.format("Cannot create trigger %s, a trigger with the 
same name already exists", def.name));
-        triggers.put(def.name, def);
-    }
-
-    public boolean containsTriggerDefinition(TriggerDefinition def)
-    {
-        return triggers.containsKey(def.name);
-    }
-
-    public boolean removeTrigger(String name)
-    {
-        return triggers.remove(name) != null;
-    }
-
     public void recordColumnDrop(ColumnDefinition def)
     {
         droppedColumns.put(def.name, new DroppedColumn(def.type, 
FBUtilities.timestampMicros()));
@@ -1366,7 +1349,7 @@ public final class CFMetaData
             .append("maxIndexInterval", maxIndexInterval)
             .append("speculativeRetry", speculativeRetry)
             .append("droppedColumns", droppedColumns)
-            .append("triggers", triggers.values())
+            .append("triggers", triggers)
             .toString();
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/16044a6f/src/java/org/apache/cassandra/config/TriggerDefinition.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/TriggerDefinition.java 
b/src/java/org/apache/cassandra/config/TriggerDefinition.java
deleted file mode 100644
index 6a84379..0000000
--- a/src/java/org/apache/cassandra/config/TriggerDefinition.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * 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.config;
-
-import com.google.common.base.Objects;
-
-public class TriggerDefinition
-{
-    public static final String CLASS = "class";
-
-    public final String name;
-
-    // For now, the only supported option is 'class'.
-    // Proper trigger parametrization will be added later.
-    public final String classOption;
-
-    public TriggerDefinition(String name, String classOption)
-    {
-        this.name = name;
-        this.classOption = classOption;
-    }
-
-    public static TriggerDefinition create(String name, String classOption)
-    {
-        return new TriggerDefinition(name, classOption);
-    }
-
-    @Override
-    public boolean equals(Object o)
-    {
-        if (this == o)
-            return true;
-
-        if (!(o instanceof TriggerDefinition))
-            return false;
-
-        TriggerDefinition td = (TriggerDefinition) o;
-
-        return Objects.equal(name, td.name) && Objects.equal(classOption, 
td.classOption);
-    }
-
-    @Override
-    public int hashCode()
-    {
-        return Objects.hashCode(name, classOption);
-    }
-
-    @Override
-    public String toString()
-    {
-        return Objects.toStringHelper(this).add("name", 
name).add("classOption", classOption).toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/16044a6f/src/java/org/apache/cassandra/cql3/statements/CreateTriggerStatement.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/CreateTriggerStatement.java 
b/src/java/org/apache/cassandra/cql3/statements/CreateTriggerStatement.java
index 6ebe0d3..c2d5616 100644
--- a/src/java/org/apache/cassandra/cql3/statements/CreateTriggerStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CreateTriggerStatement.java
@@ -22,12 +22,13 @@ import org.slf4j.LoggerFactory;
 
 import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.config.Schema;
-import org.apache.cassandra.config.TriggerDefinition;
 import org.apache.cassandra.cql3.CFName;
 import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.exceptions.InvalidRequestException;
 import org.apache.cassandra.exceptions.RequestValidationException;
 import org.apache.cassandra.exceptions.UnauthorizedException;
+import org.apache.cassandra.schema.TriggerMetadata;
+import org.apache.cassandra.schema.Triggers;
 import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.service.MigrationManager;
 import org.apache.cassandra.thrift.ThriftValidation;
@@ -71,17 +72,20 @@ public class CreateTriggerStatement extends 
SchemaAlteringStatement
     public boolean announceMigration(boolean isLocalOnly) throws 
ConfigurationException, InvalidRequestException
     {
         CFMetaData cfm = Schema.instance.getCFMetaData(keyspace(), 
columnFamily()).copy();
+        Triggers triggers = cfm.getTriggers();
 
-        TriggerDefinition triggerDefinition = 
TriggerDefinition.create(triggerName, triggerClass);
-
-        if (!ifNotExists || !cfm.containsTriggerDefinition(triggerDefinition))
+        if (triggers.get(triggerName).isPresent())
         {
-            cfm.addTriggerDefinition(triggerDefinition);
-            logger.info("Adding trigger with name {} and class {}", 
triggerName, triggerClass);
-            MigrationManager.announceColumnFamilyUpdate(cfm, false, 
isLocalOnly);
-            return true;
+            if (ifNotExists)
+                return false;
+            else
+                throw new InvalidRequestException(String.format("Trigger %s 
already exists", triggerName));
         }
-        return false;
+
+        cfm.triggers(triggers.with(TriggerMetadata.create(triggerName, 
triggerClass)));
+        logger.info("Adding trigger with name {} and class {}", triggerName, 
triggerClass);
+        MigrationManager.announceColumnFamilyUpdate(cfm, false, isLocalOnly);
+        return true;
     }
 
     public Event.SchemaChange changeEvent()

http://git-wip-us.apache.org/repos/asf/cassandra/blob/16044a6f/src/java/org/apache/cassandra/cql3/statements/DropTriggerStatement.java
----------------------------------------------------------------------
diff --git 
a/src/java/org/apache/cassandra/cql3/statements/DropTriggerStatement.java 
b/src/java/org/apache/cassandra/cql3/statements/DropTriggerStatement.java
index e3db1e1..54711de 100644
--- a/src/java/org/apache/cassandra/cql3/statements/DropTriggerStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DropTriggerStatement.java
@@ -27,6 +27,7 @@ import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.exceptions.InvalidRequestException;
 import org.apache.cassandra.exceptions.RequestValidationException;
 import org.apache.cassandra.exceptions.UnauthorizedException;
+import org.apache.cassandra.schema.Triggers;
 import org.apache.cassandra.service.ClientState;
 import org.apache.cassandra.service.MigrationManager;
 import org.apache.cassandra.thrift.ThriftValidation;
@@ -60,15 +61,20 @@ public class DropTriggerStatement extends 
SchemaAlteringStatement
     public boolean announceMigration(boolean isLocalOnly) throws 
ConfigurationException, InvalidRequestException
     {
         CFMetaData cfm = Schema.instance.getCFMetaData(keyspace(), 
columnFamily()).copy();
-        if (cfm.removeTrigger(triggerName))
+        Triggers triggers = cfm.getTriggers();
+
+        if (!triggers.get(triggerName).isPresent())
         {
-            logger.info("Dropping trigger with name {}", triggerName);
-            MigrationManager.announceColumnFamilyUpdate(cfm, false, 
isLocalOnly);
-            return true;
+            if (ifExists)
+                return false;
+            else
+                throw new InvalidRequestException(String.format("Trigger %s 
was not found", triggerName));
         }
-        if (!ifExists)
-            throw new InvalidRequestException(String.format("Trigger %s was 
not found", triggerName));
-        return false;
+
+        logger.info("Dropping trigger with name {}", triggerName);
+        cfm.triggers(triggers.without(triggerName));
+        MigrationManager.announceColumnFamilyUpdate(cfm, false, isLocalOnly);
+        return true;
     }
 
     public Event.SchemaChange changeEvent()

http://git-wip-us.apache.org/repos/asf/cassandra/blob/16044a6f/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java 
b/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
index a049194..4748820 100644
--- a/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
+++ b/src/java/org/apache/cassandra/schema/LegacySchemaMigrator.java
@@ -337,7 +337,7 @@ public final class LegacySchemaMigrator
             addDroppedColumns(cfm, tableRow.getMap("dropped_columns", 
UTF8Type.instance, LongType.instance), types);
         }
 
-        triggerRows.forEach(row -> cfm.addTriggerDefinition(readTrigger(row)));
+        cfm.triggers(createTriggersFromTriggerRows(triggerRows));
 
         return cfm;
     }
@@ -479,11 +479,18 @@ public final class LegacySchemaMigrator
         return Enum.valueOf(ColumnDefinition.Kind.class, kind.toUpperCase());
     }
 
-    private static TriggerDefinition readTrigger(UntypedResultSet.Row row)
+    private static Triggers createTriggersFromTriggerRows(UntypedResultSet 
rows)
+    {
+        Triggers.Builder triggers = 
org.apache.cassandra.schema.Triggers.builder();
+        rows.forEach(row -> triggers.add(createTriggerFromTriggerRow(row)));
+        return triggers.build();
+    }
+
+    private static TriggerMetadata 
createTriggerFromTriggerRow(UntypedResultSet.Row row)
     {
         String name = row.getString("trigger_name");
         String classOption = row.getMap("trigger_options", UTF8Type.instance, 
UTF8Type.instance).get("class");
-        return new TriggerDefinition(name, classOption);
+        return new TriggerMetadata(name, classOption);
     }
 
     /*

http://git-wip-us.apache.org/repos/asf/cassandra/blob/16044a6f/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java 
b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
index 0e40ed2..5aad59f 100644
--- a/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
+++ b/src/java/org/apache/cassandra/schema/SchemaKeyspace.java
@@ -764,7 +764,7 @@ public final class SchemaKeyspace
 
     private static Types createTypesFromPartition(RowIterator partition)
     {
-        String query = String.format("SELECT * FROM %s.%s", 
SchemaKeyspace.NAME, TYPES);
+        String query = String.format("SELECT * FROM %s.%s", NAME, TYPES);
         Types.Builder types = org.apache.cassandra.schema.Types.builder();
         QueryProcessor.resultify(query, partition).forEach(row -> 
types.add(createTypeFromRow(row)));
         return types.build();
@@ -859,7 +859,7 @@ public final class SchemaKeyspace
             for (ColumnDefinition column : table.allColumns())
                 addColumnToSchemaMutation(table, column, timestamp, mutation);
 
-            for (TriggerDefinition trigger : table.getTriggers().values())
+            for (TriggerMetadata trigger : table.getTriggers())
                 addTriggerToSchemaMutation(table, trigger, timestamp, 
mutation);
         }
 
@@ -898,19 +898,30 @@ public final class SchemaKeyspace
         for (ByteBuffer name : columnDiff.entriesDiffering().keySet())
             addColumnToSchemaMutation(newTable, 
newTable.getColumnDefinition(name), timestamp, mutation);
 
-        MapDifference<String, TriggerDefinition> triggerDiff = 
Maps.difference(oldTable.getTriggers(), newTable.getTriggers());
+        MapDifference<String, TriggerMetadata> triggerDiff = 
triggersDiff(oldTable.getTriggers(), newTable.getTriggers());
 
         // dropped triggers
-        for (TriggerDefinition trigger : 
triggerDiff.entriesOnlyOnLeft().values())
+        for (TriggerMetadata trigger : 
triggerDiff.entriesOnlyOnLeft().values())
             dropTriggerFromSchemaMutation(oldTable, trigger, timestamp, 
mutation);
 
         // newly created triggers
-        for (TriggerDefinition trigger : 
triggerDiff.entriesOnlyOnRight().values())
+        for (TriggerMetadata trigger : 
triggerDiff.entriesOnlyOnRight().values())
             addTriggerToSchemaMutation(newTable, trigger, timestamp, mutation);
 
         return mutation;
     }
 
+    private static MapDifference<String, TriggerMetadata> 
triggersDiff(Triggers before, Triggers after)
+    {
+        Map<String, TriggerMetadata> beforeMap = new HashMap<>();
+        before.forEach(t -> beforeMap.put(t.name, t));
+
+        Map<String, TriggerMetadata> afterMap = new HashMap<>();
+        after.forEach(t -> afterMap.put(t.name, t));
+
+        return Maps.difference(beforeMap, afterMap);
+    }
+
     public static Mutation makeDropTableMutation(KeyspaceMetadata keyspace, 
CFMetaData table, long timestamp)
     {
         // Include the serialized keyspace in case the target node missed a 
CREATE KEYSPACE migration (see CASSANDRA-5631).
@@ -921,7 +932,7 @@ public final class SchemaKeyspace
         for (ColumnDefinition column : table.allColumns())
             dropColumnFromSchemaMutation(table, column, timestamp, mutation);
 
-        for (TriggerDefinition trigger : table.getTriggers().values())
+        for (TriggerMetadata trigger : table.getTriggers())
             dropTriggerFromSchemaMutation(table, trigger, timestamp, mutation);
 
         return mutation;
@@ -979,9 +990,7 @@ public final class SchemaKeyspace
 
         CFMetaData cfm = readSchemaPartitionForTableAndApply(COLUMNS, ksName, 
cfName, partition -> createTableFromTableRowAndColumnsPartition(result, 
partition));
 
-        readSchemaPartitionForTableAndApply(TRIGGERS, ksName, cfName,
-            partition -> { 
createTriggersFromTriggersPartition(partition).forEach(cfm::addTriggerDefinition);
 return null; }
-        );
+        readSchemaPartitionForTableAndApply(TRIGGERS, ksName, cfName, 
partition -> cfm.triggers(createTriggersFromTriggersPartition(partition)));
 
         return cfm;
     }
@@ -1248,7 +1257,7 @@ public final class SchemaKeyspace
      * Trigger metadata serialization/deserialization.
      */
 
-    private static void addTriggerToSchemaMutation(CFMetaData table, 
TriggerDefinition trigger, long timestamp, Mutation mutation)
+    private static void addTriggerToSchemaMutation(CFMetaData table, 
TriggerMetadata trigger, long timestamp, Mutation mutation)
     {
         new RowUpdateBuilder(Triggers, timestamp, mutation)
             .clustering(table.cfName, trigger.name)
@@ -1256,7 +1265,7 @@ public final class SchemaKeyspace
             .build();
     }
 
-    private static void dropTriggerFromSchemaMutation(CFMetaData table, 
TriggerDefinition trigger, long timestamp, Mutation mutation)
+    private static void dropTriggerFromSchemaMutation(CFMetaData table, 
TriggerMetadata trigger, long timestamp, Mutation mutation)
     {
         RowUpdateBuilder.deleteRow(Triggers, timestamp, mutation, 
table.cfName, trigger.name);
     }
@@ -1267,17 +1276,19 @@ public final class SchemaKeyspace
      * @param partition storage-level partition containing the trigger 
definitions
      * @return the list of processed TriggerDefinitions
      */
-    private static List<TriggerDefinition> 
createTriggersFromTriggersPartition(RowIterator partition)
+    private static Triggers createTriggersFromTriggersPartition(RowIterator 
partition)
     {
-        List<TriggerDefinition> triggers = new ArrayList<>();
+        Triggers.Builder triggers = 
org.apache.cassandra.schema.Triggers.builder();
         String query = String.format("SELECT * FROM %s.%s", NAME, TRIGGERS);
-        for (UntypedResultSet.Row row : QueryProcessor.resultify(query, 
partition))
-        {
-            String name = row.getString("trigger_name");
-            String classOption = row.getMap("trigger_options", 
UTF8Type.instance, UTF8Type.instance).get("class");
-            triggers.add(new TriggerDefinition(name, classOption));
-        }
-        return triggers;
+        QueryProcessor.resultify(query, partition).forEach(row -> 
triggers.add(createTriggerFromTriggerRow(row)));
+        return triggers.build();
+    }
+
+    private static TriggerMetadata 
createTriggerFromTriggerRow(UntypedResultSet.Row row)
+    {
+        String name = row.getString("trigger_name");
+        String classOption = row.getMap("trigger_options", UTF8Type.instance, 
UTF8Type.instance).get("class");
+        return new TriggerMetadata(name, classOption);
     }
 
     /*

http://git-wip-us.apache.org/repos/asf/cassandra/blob/16044a6f/src/java/org/apache/cassandra/schema/TriggerMetadata.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/schema/TriggerMetadata.java 
b/src/java/org/apache/cassandra/schema/TriggerMetadata.java
new file mode 100644
index 0000000..2e0d547
--- /dev/null
+++ b/src/java/org/apache/cassandra/schema/TriggerMetadata.java
@@ -0,0 +1,72 @@
+/*
+ * 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.schema;
+
+import com.google.common.base.Objects;
+
+public final class TriggerMetadata
+{
+    public static final String CLASS = "class";
+
+    public final String name;
+
+    // For now, the only supported option is 'class'.
+    // Proper trigger parametrization will be added later.
+    public final String classOption;
+
+    public TriggerMetadata(String name, String classOption)
+    {
+        this.name = name;
+        this.classOption = classOption;
+    }
+
+    public static TriggerMetadata create(String name, String classOption)
+    {
+        return new TriggerMetadata(name, classOption);
+    }
+
+    @Override
+    public boolean equals(Object o)
+    {
+        if (this == o)
+            return true;
+
+        if (!(o instanceof TriggerMetadata))
+            return false;
+
+        TriggerMetadata td = (TriggerMetadata) o;
+
+        return name.equals(td.name) && classOption.equals(td.classOption);
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return Objects.hashCode(name, classOption);
+    }
+
+    @Override
+    public String toString()
+    {
+        return Objects.toStringHelper(this)
+                      .add("name", name)
+                      .add("class", classOption)
+                      .toString();
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/16044a6f/src/java/org/apache/cassandra/schema/Triggers.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/schema/Triggers.java 
b/src/java/org/apache/cassandra/schema/Triggers.java
new file mode 100644
index 0000000..bb39f1f
--- /dev/null
+++ b/src/java/org/apache/cassandra/schema/Triggers.java
@@ -0,0 +1,137 @@
+/*
+ * 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.schema;
+
+import java.util.Iterator;
+import java.util.Optional;
+
+import com.google.common.collect.ImmutableMap;
+
+import static com.google.common.collect.Iterables.filter;
+
+public final class Triggers implements Iterable<TriggerMetadata>
+{
+    private final ImmutableMap<String, TriggerMetadata> triggers;
+
+    private Triggers(Builder builder)
+    {
+        triggers = builder.triggers.build();
+    }
+
+    public static Builder builder()
+    {
+        return new Builder();
+    }
+
+    public static Triggers none()
+    {
+        return builder().build();
+    }
+
+    public Iterator<TriggerMetadata> iterator()
+    {
+        return triggers.values().iterator();
+    }
+
+    public int size()
+    {
+        return triggers.size();
+    }
+
+    public boolean isEmpty()
+    {
+        return triggers.isEmpty();
+    }
+
+    /**
+     * Get the trigger with the specified name
+     *
+     * @param name a non-qualified trigger name
+     * @return an empty {@link Optional} if the trigger name is not found; a 
non-empty optional of {@link TriggerMetadata} otherwise
+     */
+    public Optional<TriggerMetadata> get(String name)
+    {
+        return Optional.ofNullable(triggers.get(name));
+    }
+
+    /**
+     * Create a Triggers instance with the provided trigger added
+     */
+    public Triggers with(TriggerMetadata trigger)
+    {
+        if (get(trigger.name).isPresent())
+            throw new IllegalStateException(String.format("Trigger %s already 
exists", trigger.name));
+
+        return builder().add(this).add(trigger).build();
+    }
+
+    /**
+     * Creates a Triggers instance with the trigger with the provided name 
removed
+     */
+    public Triggers without(String name)
+    {
+        TriggerMetadata trigger =
+            get(name).orElseThrow(() -> new 
IllegalStateException(String.format("Trigger %s doesn't exists", name)));
+
+        return builder().add(filter(this, t -> t != trigger)).build();
+    }
+
+    @Override
+    public boolean equals(Object o)
+    {
+        return this == o || (o instanceof Triggers && 
triggers.equals(((Triggers) o).triggers));
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return triggers.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+        return triggers.values().toString();
+    }
+
+    public static final class Builder
+    {
+        final ImmutableMap.Builder<String, TriggerMetadata> triggers = new 
ImmutableMap.Builder<>();
+
+        private Builder()
+        {
+        }
+
+        public Triggers build()
+        {
+            return new Triggers(this);
+        }
+
+        public Builder add(TriggerMetadata trigger)
+        {
+            triggers.put(trigger.name, trigger);
+            return this;
+        }
+
+        public Builder add(Iterable<TriggerMetadata> triggers)
+        {
+            triggers.forEach(this::add);
+            return this;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/16044a6f/src/java/org/apache/cassandra/thrift/ThriftConversion.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/thrift/ThriftConversion.java 
b/src/java/org/apache/cassandra/thrift/ThriftConversion.java
index 3e0c8f4..2b210e9 100644
--- a/src/java/org/apache/cassandra/thrift/ThriftConversion.java
+++ b/src/java/org/apache/cassandra/thrift/ThriftConversion.java
@@ -42,6 +42,8 @@ import org.apache.cassandra.schema.KeyspaceMetadata;
 import org.apache.cassandra.schema.KeyspaceParams;
 import org.apache.cassandra.schema.SchemaKeyspace;
 import org.apache.cassandra.schema.Tables;
+import org.apache.cassandra.schema.TriggerMetadata;
+import org.apache.cassandra.schema.Triggers;
 import org.apache.cassandra.serializers.MarshalException;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.UUIDGen;
@@ -463,7 +465,7 @@ public class ThriftConversion
         def.setCells_per_row_to_cache(cfm.getCaching().toThriftCellsPerRow());
         def.setDefault_time_to_live(cfm.getDefaultTimeToLive());
         def.setSpeculative_retry(cfm.getSpeculativeRetry().toString());
-        
def.setTriggers(triggerDefinitionsToThrift(cfm.getTriggers().values()));
+        def.setTriggers(triggerDefinitionsToThrift(cfm.getTriggers()));
 
         return def;
     }
@@ -542,23 +544,22 @@ public class ThriftConversion
         return thriftDefs;
     }
 
-    private static Map<String, TriggerDefinition> 
triggerDefinitionsFromThrift(List<TriggerDef> thriftDefs)
+    private static Triggers triggerDefinitionsFromThrift(List<TriggerDef> 
thriftDefs)
     {
-        Map<String, TriggerDefinition> triggerDefinitions = new HashMap<>();
+        Triggers.Builder triggers = Triggers.builder();
         for (TriggerDef thriftDef : thriftDefs)
-            triggerDefinitions.put(thriftDef.getName(),
-                                   new TriggerDefinition(thriftDef.getName(), 
thriftDef.getOptions().get(TriggerDefinition.CLASS)));
-        return triggerDefinitions;
+            triggers.add(new TriggerMetadata(thriftDef.getName(), 
thriftDef.getOptions().get(TriggerMetadata.CLASS)));
+        return triggers.build();
     }
 
-    private static List<TriggerDef> 
triggerDefinitionsToThrift(Collection<TriggerDefinition> triggers)
+    private static List<TriggerDef> triggerDefinitionsToThrift(Triggers 
triggers)
     {
-        List<TriggerDef> thriftDefs = new ArrayList<>(triggers.size());
-        for (TriggerDefinition def : triggers)
+        List<TriggerDef> thriftDefs = new ArrayList<>();
+        for (TriggerMetadata def : triggers)
         {
             TriggerDef td = new TriggerDef();
             td.setName(def.name);
-            td.setOptions(Collections.singletonMap(TriggerDefinition.CLASS, 
def.classOption));
+            td.setOptions(Collections.singletonMap(TriggerMetadata.CLASS, 
def.classOption));
             thriftDefs.add(td);
         }
         return thriftDefs;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/16044a6f/src/java/org/apache/cassandra/triggers/TriggerExecutor.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/triggers/TriggerExecutor.java 
b/src/java/org/apache/cassandra/triggers/TriggerExecutor.java
index 071a973..d75d2f1 100644
--- a/src/java/org/apache/cassandra/triggers/TriggerExecutor.java
+++ b/src/java/org/apache/cassandra/triggers/TriggerExecutor.java
@@ -28,12 +28,12 @@ import com.google.common.collect.Lists;
 import com.google.common.collect.ListMultimap;
 import com.google.common.collect.Maps;
 
-import org.apache.cassandra.config.TriggerDefinition;
 import org.apache.cassandra.cql3.QueryProcessor;
 import org.apache.cassandra.db.*;
 import org.apache.cassandra.db.partitions.PartitionUpdate;
-import org.apache.cassandra.db.marshal.AbstractType;
 import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.schema.TriggerMetadata;
+import org.apache.cassandra.schema.Triggers;
 import org.apache.cassandra.utils.FBUtilities;
 import org.apache.cassandra.utils.Pair;
 
@@ -72,7 +72,6 @@ public class TriggerExecutor
      * key as the primary update; if not, InvalidRequestException is thrown. 
If no
      * additional mutations are generated, the original updates are returned 
unmodified.
      *
-     * @param key partition key for the update
      * @param updates partition update to be applied, contains the merge of 
the original
      *                update and any generated mutations
      * @return the final update to be applied, the original update merged with 
any
@@ -211,14 +210,14 @@ public class TriggerExecutor
      */
     private List<Mutation> executeInternal(PartitionUpdate update)
     {
-        Map<String, TriggerDefinition> triggers = 
update.metadata().getTriggers();
+        Triggers triggers = update.metadata().getTriggers();
         if (triggers.isEmpty())
             return null;
         List<Mutation> tmutations = Lists.newLinkedList();
         Thread.currentThread().setContextClassLoader(customClassLoader);
         try
         {
-            for (TriggerDefinition td : triggers.values())
+            for (TriggerMetadata td : triggers)
             {
                 ITrigger trigger = cachedTriggers.get(td.classOption);
                 if (trigger == null)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/16044a6f/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java
----------------------------------------------------------------------
diff --git 
a/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java 
b/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java
index 18f2db4..053d291 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/CreateTest.java
@@ -18,17 +18,14 @@
 
 package org.apache.cassandra.cql3.validation.operations;
 
-import java.nio.ByteBuffer;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.UUID;
 
-import org.junit.Assert;
 import org.junit.Test;
 
 import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.config.Schema;
-import org.apache.cassandra.config.TriggerDefinition;
 import org.apache.cassandra.cql3.CQLTester;
 import org.apache.cassandra.db.Mutation;
 import org.apache.cassandra.db.partitions.Partition;
@@ -403,12 +400,12 @@ public class CreateTest extends CQLTester
     {
         createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a))");
         execute("CREATE TRIGGER trigger_1 ON %s USING '" + 
TestTrigger.class.getName() + "'");
-        assertTriggerExists("trigger_1", TestTrigger.class);
+        assertTriggerExists("trigger_1");
         execute("CREATE TRIGGER trigger_2 ON %s USING '" + 
TestTrigger.class.getName() + "'");
-        assertTriggerExists("trigger_2", TestTrigger.class);
+        assertTriggerExists("trigger_2");
         assertInvalid("CREATE TRIGGER trigger_1 ON %s USING '" + 
TestTrigger.class.getName() + "'");
         execute("CREATE TRIGGER \"Trigger 3\" ON %s USING '" + 
TestTrigger.class.getName() + "'");
-        assertTriggerExists("Trigger 3", TestTrigger.class);
+        assertTriggerExists("Trigger 3");
     }
 
     @Test
@@ -417,10 +414,10 @@ public class CreateTest extends CQLTester
         createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a, 
b))");
 
         execute("CREATE TRIGGER IF NOT EXISTS trigger_1 ON %s USING '" + 
TestTrigger.class.getName() + "'");
-        assertTriggerExists("trigger_1", TestTrigger.class);
+        assertTriggerExists("trigger_1");
 
         execute("CREATE TRIGGER IF NOT EXISTS trigger_1 ON %s USING '" + 
TestTrigger.class.getName() + "'");
-        assertTriggerExists("trigger_1", TestTrigger.class);
+        assertTriggerExists("trigger_1");
     }
 
     @Test
@@ -429,21 +426,21 @@ public class CreateTest extends CQLTester
         createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a))");
 
         execute("CREATE TRIGGER trigger_1 ON %s USING '" + 
TestTrigger.class.getName() + "'");
-        assertTriggerExists("trigger_1", TestTrigger.class);
+        assertTriggerExists("trigger_1");
 
         execute("DROP TRIGGER trigger_1 ON %s");
-        assertTriggerDoesNotExists("trigger_1", TestTrigger.class);
+        assertTriggerDoesNotExists("trigger_1");
 
         execute("CREATE TRIGGER trigger_1 ON %s USING '" + 
TestTrigger.class.getName() + "'");
-        assertTriggerExists("trigger_1", TestTrigger.class);
+        assertTriggerExists("trigger_1");
 
         assertInvalid("DROP TRIGGER trigger_2 ON %s");
 
         execute("CREATE TRIGGER \"Trigger 3\" ON %s USING '" + 
TestTrigger.class.getName() + "'");
-        assertTriggerExists("Trigger 3", TestTrigger.class);
+        assertTriggerExists("Trigger 3");
 
         execute("DROP TRIGGER \"Trigger 3\" ON %s");
-        assertTriggerDoesNotExists("Trigger 3", TestTrigger.class);
+        assertTriggerDoesNotExists("Trigger 3");
     }
 
     @Test
@@ -452,13 +449,13 @@ public class CreateTest extends CQLTester
         createTable("CREATE TABLE %s (a int, b int, c int, PRIMARY KEY (a))");
 
         execute("DROP TRIGGER IF EXISTS trigger_1 ON %s");
-        assertTriggerDoesNotExists("trigger_1", TestTrigger.class);
+        assertTriggerDoesNotExists("trigger_1");
 
         execute("CREATE TRIGGER trigger_1 ON %s USING '" + 
TestTrigger.class.getName() + "'");
-        assertTriggerExists("trigger_1", TestTrigger.class);
+        assertTriggerExists("trigger_1");
 
         execute("DROP TRIGGER IF EXISTS trigger_1 ON %s");
-        assertTriggerDoesNotExists("trigger_1", TestTrigger.class);
+        assertTriggerDoesNotExists("trigger_1");
     }
 
     @Test
@@ -497,26 +494,23 @@ public class CreateTest extends CQLTester
     // tests CASSANDRA-9565
     public void testDoubleWith() throws Throwable
     {
-        String[] stmts = new String[] { "CREATE KEYSPACE WITH WITH 
DURABLE_WRITES = true",
-                                        "CREATE KEYSPACE ks WITH WITH 
DURABLE_WRITES = true" };
+        String[] stmts = { "CREATE KEYSPACE WITH WITH DURABLE_WRITES = true",
+                           "CREATE KEYSPACE ks WITH WITH DURABLE_WRITES = 
true" };
 
-        for (String stmt : stmts) {
+        for (String stmt : stmts)
             assertInvalidSyntaxMessage("no viable alternative at input 
'WITH'", stmt);
-        }
     }
 
-    private void assertTriggerExists(String name, Class<?> clazz)
+    private void assertTriggerExists(String name)
     {
         CFMetaData cfm = Schema.instance.getCFMetaData(keyspace(), 
currentTable()).copy();
-        assertTrue("the trigger does not exist", 
cfm.containsTriggerDefinition(TriggerDefinition.create(name,
-                                                                               
                         clazz.getName())));
+        assertTrue("the trigger does not exist", 
cfm.getTriggers().get(name).isPresent());
     }
 
-    private void assertTriggerDoesNotExists(String name, Class<?> clazz)
+    private void assertTriggerDoesNotExists(String name)
     {
         CFMetaData cfm = Schema.instance.getCFMetaData(keyspace(), 
currentTable()).copy();
-        Assert.assertFalse("the trigger exists", 
cfm.containsTriggerDefinition(TriggerDefinition.create(name,
-                                                                               
                         clazz.getName())));
+        assertFalse("the trigger exists", 
cfm.getTriggers().get(name).isPresent());
     }
 
     public static class TestTrigger implements ITrigger

http://git-wip-us.apache.org/repos/asf/cassandra/blob/16044a6f/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java
----------------------------------------------------------------------
diff --git 
a/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java 
b/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java
index b4149a0..17cffaf 100644
--- a/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java
+++ b/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java
@@ -248,9 +248,11 @@ public class LegacySchemaMigratorTest
     {
         String keyspace = KEYSPACE_PREFIX + "Triggers";
 
+        Triggers.Builder triggers = Triggers.builder();
         CFMetaData table = SchemaLoader.standardCFMD(keyspace, "WithTriggers");
         for (int i = 0; i < 10; i++)
-            table.addTriggerDefinition(new TriggerDefinition("trigger" + i, 
"DummyTrigger" + i));
+            triggers.add(new TriggerMetadata("trigger" + i, "DummyTrigger" + 
i));
+        table.triggers(triggers.build());
 
         return KeyspaceMetadata.create(keyspace, KeyspaceParams.simple(1), 
Tables.of(table));
     }
@@ -418,7 +420,7 @@ public class LegacySchemaMigratorTest
             for (ColumnDefinition column : table.allColumns())
                 addColumnToSchemaMutation(table, column, timestamp, mutation);
 
-            for (TriggerDefinition trigger : table.getTriggers().values())
+            for (TriggerMetadata trigger : table.getTriggers())
                 addTriggerToSchemaMutation(table, trigger, timestamp, 
mutation);
         }
 
@@ -451,7 +453,7 @@ public class LegacySchemaMigratorTest
         return kind.toString().toLowerCase();
     }
 
-    private static void addTriggerToSchemaMutation(CFMetaData table, 
TriggerDefinition trigger, long timestamp, Mutation mutation)
+    private static void addTriggerToSchemaMutation(CFMetaData table, 
TriggerMetadata trigger, long timestamp, Mutation mutation)
     {
         new RowUpdateBuilder(SystemKeyspace.LegacyTriggers, timestamp, 
mutation)
             .clustering(table.cfName, trigger.name)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/16044a6f/test/unit/org/apache/cassandra/triggers/TriggerExecutorTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/triggers/TriggerExecutorTest.java 
b/test/unit/org/apache/cassandra/triggers/TriggerExecutorTest.java
index a5d79d3..0cf7491 100644
--- a/test/unit/org/apache/cassandra/triggers/TriggerExecutorTest.java
+++ b/test/unit/org/apache/cassandra/triggers/TriggerExecutorTest.java
@@ -23,7 +23,6 @@ import org.junit.Test;
 
 import org.apache.cassandra.Util;
 import org.apache.cassandra.config.CFMetaData;
-import org.apache.cassandra.config.TriggerDefinition;
 import org.apache.cassandra.db.*;
 import org.apache.cassandra.db.rows.UnfilteredRowIterators;
 import org.apache.cassandra.db.rows.Cell;
@@ -34,6 +33,7 @@ import org.apache.cassandra.db.partitions.Partition;
 import org.apache.cassandra.db.partitions.PartitionUpdate;
 import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.exceptions.InvalidRequestException;
+import org.apache.cassandra.schema.TriggerMetadata;
 import org.apache.cassandra.utils.FBUtilities;
 
 import static org.apache.cassandra.utils.ByteBufferUtil.bytes;
@@ -46,7 +46,7 @@ public class TriggerExecutorTest
     @Test
     public void sameKeySameCfColumnFamilies() throws ConfigurationException, 
InvalidRequestException
     {
-        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerDefinition.create("test", SameKeySameCfTrigger.class.getName()));
+        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerMetadata.create("test", SameKeySameCfTrigger.class.getName()));
         PartitionUpdate mutated = 
TriggerExecutor.instance.execute(makeCf(metadata, "k1", "v1", null));
 
         RowIterator rowIterator = 
UnfilteredRowIterators.filter(mutated.unfilteredIterator(), 
FBUtilities.nowInSeconds());
@@ -60,21 +60,21 @@ public class TriggerExecutorTest
     @Test(expected = InvalidRequestException.class)
     public void sameKeyDifferentCfColumnFamilies() throws 
ConfigurationException, InvalidRequestException
     {
-        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerDefinition.create("test", SameKeyDifferentCfTrigger.class.getName()));
+        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerMetadata.create("test", SameKeyDifferentCfTrigger.class.getName()));
         TriggerExecutor.instance.execute(makeCf(metadata, "k1", "v1", null));
     }
 
     @Test(expected = InvalidRequestException.class)
     public void differentKeyColumnFamilies() throws ConfigurationException, 
InvalidRequestException
     {
-        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerDefinition.create("test", DifferentKeyTrigger.class.getName()));
+        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerMetadata.create("test", DifferentKeyTrigger.class.getName()));
         TriggerExecutor.instance.execute(makeCf(metadata, "k1", "v1", null));
     }
 
     @Test
     public void noTriggerMutations() throws ConfigurationException, 
InvalidRequestException
     {
-        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerDefinition.create("test", NoOpTrigger.class.getName()));
+        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerMetadata.create("test", NoOpTrigger.class.getName()));
         Mutation rm = new Mutation(makeCf(metadata, "k1", "v1", null));
         
assertNull(TriggerExecutor.instance.execute(Collections.singletonList(rm)));
     }
@@ -82,7 +82,7 @@ public class TriggerExecutorTest
     @Test
     public void sameKeySameCfRowMutations() throws ConfigurationException, 
InvalidRequestException
     {
-        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerDefinition.create("test", SameKeySameCfTrigger.class.getName()));
+        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerMetadata.create("test", SameKeySameCfTrigger.class.getName()));
         PartitionUpdate cf1 = makeCf(metadata, "k1", "k1v1", null);
         PartitionUpdate cf2 = makeCf(metadata, "k2", "k2v1", null);
         Mutation rm1 = new Mutation("ks1", cf1.partitionKey()).add(cf1);
@@ -108,7 +108,7 @@ public class TriggerExecutorTest
     @Test
     public void sameKeySameCfPartialRowMutations() throws 
ConfigurationException, InvalidRequestException
     {
-        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerDefinition.create("test", SameKeySameCfPartialTrigger.class.getName()));
+        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerMetadata.create("test", SameKeySameCfPartialTrigger.class.getName()));
         PartitionUpdate cf1 = makeCf(metadata, "k1", "k1v1", null);
         PartitionUpdate cf2 = makeCf(metadata, "k2", "k2v1", null);
         Mutation rm1 = new Mutation("ks1", cf1.partitionKey()).add(cf1);
@@ -134,7 +134,7 @@ public class TriggerExecutorTest
     @Test
     public void sameKeyDifferentCfRowMutations() throws 
ConfigurationException, InvalidRequestException
     {
-        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerDefinition.create("test", SameKeyDifferentCfTrigger.class.getName()));
+        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerMetadata.create("test", SameKeyDifferentCfTrigger.class.getName()));
         PartitionUpdate cf1 = makeCf(metadata, "k1", "k1v1", null);
         PartitionUpdate cf2 = makeCf(metadata, "k2", "k2v1", null);
         Mutation rm1 = new Mutation("ks1", cf1.partitionKey()).add(cf1);
@@ -185,7 +185,7 @@ public class TriggerExecutorTest
     @Test
     public void sameKeyDifferentKsRowMutations() throws 
ConfigurationException, InvalidRequestException
     {
-        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerDefinition.create("test", SameKeyDifferentKsTrigger.class.getName()));
+        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerMetadata.create("test", SameKeyDifferentKsTrigger.class.getName()));
         PartitionUpdate cf1 = makeCf(metadata, "k1", "k1v1", null);
         PartitionUpdate cf2 = makeCf(metadata, "k2", "k2v1", null);
         Mutation rm1 = new Mutation("ks1", cf1.partitionKey()).add(cf1);
@@ -224,7 +224,7 @@ public class TriggerExecutorTest
     public void differentKeyRowMutations() throws ConfigurationException, 
InvalidRequestException
     {
 
-        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerDefinition.create("test", DifferentKeyTrigger.class.getName()));
+        CFMetaData metadata = makeCfMetaData("ks1", "cf1", 
TriggerMetadata.create("test", DifferentKeyTrigger.class.getName()));
         PartitionUpdate cf1 = makeCf(metadata, "k1", "v1", null);
         Mutation rm = new Mutation("ks1", cf1.partitionKey()).add(cf1);
 
@@ -248,7 +248,7 @@ public class TriggerExecutorTest
         assertNull(row.getCell(metadata.getColumnDefinition(bytes("c1"))));
     }
 
-    private static CFMetaData makeCfMetaData(String ks, String cf, 
TriggerDefinition trigger)
+    private static CFMetaData makeCfMetaData(String ks, String cf, 
TriggerMetadata trigger)
     {
         CFMetaData metadata = CFMetaData.Builder.create(ks, cf)
                 .addPartitionKey("pkey", UTF8Type.instance)
@@ -259,7 +259,7 @@ public class TriggerExecutorTest
         try
         {
             if (trigger != null)
-                metadata.addTriggerDefinition(trigger);
+                metadata.triggers(metadata.getTriggers().with(trigger));
         }
         catch (InvalidRequestException e)
         {

http://git-wip-us.apache.org/repos/asf/cassandra/blob/16044a6f/test/unit/org/apache/cassandra/triggers/TriggersSchemaTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/triggers/TriggersSchemaTest.java 
b/test/unit/org/apache/cassandra/triggers/TriggersSchemaTest.java
index 8d66ca7..211cc9a 100644
--- a/test/unit/org/apache/cassandra/triggers/TriggersSchemaTest.java
+++ b/test/unit/org/apache/cassandra/triggers/TriggersSchemaTest.java
@@ -23,11 +23,11 @@ import org.junit.Test;
 import org.apache.cassandra.SchemaLoader;
 import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.config.Schema;
-import org.apache.cassandra.config.TriggerDefinition;
 import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.schema.KeyspaceMetadata;
 import org.apache.cassandra.schema.KeyspaceParams;
 import org.apache.cassandra.schema.Tables;
+import org.apache.cassandra.schema.TriggerMetadata;
 import org.apache.cassandra.service.MigrationManager;
 
 import static org.junit.Assert.*;
@@ -48,16 +48,16 @@ public class TriggersSchemaTest
     @Test
     public void newKsContainsCfWithTrigger() throws Exception
     {
-        TriggerDefinition td = TriggerDefinition.create(triggerName, 
triggerClass);
+        TriggerMetadata td = TriggerMetadata.create(triggerName, triggerClass);
         CFMetaData cfm1 = CFMetaData.compile(String.format("CREATE TABLE %s (k 
int PRIMARY KEY, v int)", cfName), ksName);
-        cfm1.addTriggerDefinition(td);
+        cfm1.triggers(cfm1.getTriggers().with(td));
         KeyspaceMetadata ksm = KeyspaceMetadata.create(ksName, 
KeyspaceParams.simple(1), Tables.of(cfm1));
         MigrationManager.announceNewKeyspace(ksm);
 
         CFMetaData cfm2 = Schema.instance.getCFMetaData(ksName, cfName);
         assertFalse(cfm2.getTriggers().isEmpty());
         assertEquals(1, cfm2.getTriggers().size());
-        assertEquals(td, cfm2.getTriggers().get(triggerName));
+        assertEquals(td, cfm2.getTriggers().get(triggerName).get());
     }
 
     @Test
@@ -67,15 +67,15 @@ public class TriggersSchemaTest
         MigrationManager.announceNewKeyspace(ksm);
 
         CFMetaData cfm1 = CFMetaData.compile(String.format("CREATE TABLE %s (k 
int PRIMARY KEY, v int)", cfName), ksName);
-        TriggerDefinition td = TriggerDefinition.create(triggerName, 
triggerClass);
-        cfm1.addTriggerDefinition(td);
+        TriggerMetadata td = TriggerMetadata.create(triggerName, triggerClass);
+        cfm1.triggers(cfm1.getTriggers().with(td));
 
         MigrationManager.announceNewColumnFamily(cfm1);
 
         CFMetaData cfm2 = Schema.instance.getCFMetaData(ksName, cfName);
         assertFalse(cfm2.getTriggers().isEmpty());
         assertEquals(1, cfm2.getTriggers().size());
-        assertEquals(td, cfm2.getTriggers().get(triggerName));
+        assertEquals(td, cfm2.getTriggers().get(triggerName).get());
     }
 
     @Test
@@ -86,27 +86,27 @@ public class TriggersSchemaTest
         MigrationManager.announceNewKeyspace(ksm);
 
         CFMetaData cfm2 = Schema.instance.getCFMetaData(ksName, cfName).copy();
-        TriggerDefinition td = TriggerDefinition.create(triggerName, 
triggerClass);
-        cfm2.addTriggerDefinition(td);
+        TriggerMetadata td = TriggerMetadata.create(triggerName, triggerClass);
+        cfm2.triggers(cfm2.getTriggers().with(td));
         MigrationManager.announceColumnFamilyUpdate(cfm2, false);
 
         CFMetaData cfm3 = Schema.instance.getCFMetaData(ksName, cfName);
         assertFalse(cfm3.getTriggers().isEmpty());
         assertEquals(1, cfm3.getTriggers().size());
-        assertEquals(td, cfm3.getTriggers().get(triggerName));
+        assertEquals(td, cfm3.getTriggers().get(triggerName).get());
     }
 
     @Test
     public void removeTriggerFromCf() throws Exception
     {
-        TriggerDefinition td = TriggerDefinition.create(triggerName, 
triggerClass);
+        TriggerMetadata td = TriggerMetadata.create(triggerName, triggerClass);
         CFMetaData cfm1 = CFMetaData.compile(String.format("CREATE TABLE %s (k 
int PRIMARY KEY, v int)", cfName), ksName);
-        cfm1.addTriggerDefinition(td);
+        cfm1.triggers(cfm1.getTriggers().with(td));
         KeyspaceMetadata ksm = KeyspaceMetadata.create(ksName, 
KeyspaceParams.simple(1), Tables.of(cfm1));
         MigrationManager.announceNewKeyspace(ksm);
 
         CFMetaData cfm2 = Schema.instance.getCFMetaData(ksName, cfName).copy();
-        cfm2.removeTrigger(triggerName);
+        cfm2.triggers(cfm2.getTriggers().without(triggerName));
         MigrationManager.announceColumnFamilyUpdate(cfm2, false);
 
         CFMetaData cfm3 = Schema.instance.getCFMetaData(ksName, cfName).copy();

Reply via email to