cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From alek...@apache.org
Subject cassandra git commit: Replace mutable UTMetaData with immutable Types in KSMetaData
Date Tue, 30 Jun 2015 12:34:42 GMT
Repository: cassandra
Updated Branches:
  refs/heads/trunk 543efe924 -> 2f2b58da2


Replace mutable UTMetaData with immutable Types in KSMetaData

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


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

Branch: refs/heads/trunk
Commit: 2f2b58da22e610cfcd7b994938a9a717cbda1bdc
Parents: 543efe9
Author: Aleksey Yeschenko <aleksey@apache.org>
Authored: Tue Jun 30 15:33:48 2015 +0300
Committer: Aleksey Yeschenko <aleksey@apache.org>
Committed: Tue Jun 30 15:34:55 2015 +0300

----------------------------------------------------------------------
 .../org/apache/cassandra/config/KSMetaData.java |  34 +++--
 .../org/apache/cassandra/config/Schema.java     |  36 ++---
 .../org/apache/cassandra/config/UTMetaData.java |  76 ----------
 .../org/apache/cassandra/cql3/CQL3Type.java     |   2 +-
 .../cassandra/cql3/functions/UDFunction.java    |   2 +-
 .../cql3/statements/AlterTypeStatement.java     |   9 +-
 .../cql3/statements/CreateTypeStatement.java    |   4 +-
 .../cql3/statements/DropTypeStatement.java      |   7 +-
 .../cassandra/schema/LegacySchemaTables.java    |  18 +--
 src/java/org/apache/cassandra/schema/Types.java | 147 +++++++++++++++++++
 .../selection/SelectionColumnMappingTest.java   |   2 +-
 11 files changed, 199 insertions(+), 138 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cassandra/blob/2f2b58da/src/java/org/apache/cassandra/config/KSMetaData.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/KSMetaData.java b/src/java/org/apache/cassandra/config/KSMetaData.java
index a325a80..4afba19 100644
--- a/src/java/org/apache/cassandra/config/KSMetaData.java
+++ b/src/java/org/apache/cassandra/config/KSMetaData.java
@@ -24,6 +24,7 @@ import com.google.common.base.Objects;
 import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.locator.*;
 import org.apache.cassandra.schema.Functions;
+import org.apache.cassandra.schema.Types;
 import org.apache.cassandra.service.StorageService;
 
 public final class KSMetaData
@@ -34,7 +35,7 @@ public final class KSMetaData
     private final Map<String, CFMetaData> cfMetaData;
     public final boolean durableWrites;
 
-    public final UTMetaData userTypes;
+    public final Types types;
     public final Functions functions;
 
     public KSMetaData(String name,
@@ -42,7 +43,7 @@ public final class KSMetaData
                       Map<String, String> strategyOptions,
                       boolean durableWrites)
     {
-        this(name, strategyClass, strategyOptions, durableWrites, Collections.<CFMetaData>emptyList(),
new UTMetaData(), Functions.none());
+        this(name, strategyClass, strategyOptions, durableWrites, Collections.<CFMetaData>emptyList(),
Types.none(), Functions.none());
     }
 
     public KSMetaData(String name,
@@ -51,7 +52,7 @@ public final class KSMetaData
                       boolean durableWrites,
                       Iterable<CFMetaData> cfDefs)
     {
-        this(name, strategyClass, strategyOptions, durableWrites, cfDefs, new UTMetaData(),
Functions.none());
+        this(name, strategyClass, strategyOptions, durableWrites, cfDefs, Types.none(), Functions.none());
     }
 
     public KSMetaData(String name,
@@ -61,7 +62,7 @@ public final class KSMetaData
                       Iterable<CFMetaData> cfDefs,
                       Functions functions)
     {
-        this(name, strategyClass, strategyOptions, durableWrites, cfDefs, new UTMetaData(),
functions);
+        this(name, strategyClass, strategyOptions, durableWrites, cfDefs, Types.none(), functions);
     }
 
     private KSMetaData(String name,
@@ -69,7 +70,7 @@ public final class KSMetaData
                        Map<String, String> strategyOptions,
                        boolean durableWrites,
                        Iterable<CFMetaData> cfDefs,
-                       UTMetaData userTypes,
+                       Types types,
                        Functions functions)
     {
         this.name = name;
@@ -80,7 +81,7 @@ public final class KSMetaData
             cfmap.put(cfm.cfName, cfm);
         this.cfMetaData = Collections.unmodifiableMap(cfmap);
         this.durableWrites = durableWrites;
-        this.userTypes = userTypes;
+        this.types = types;
         this.functions = functions;
     }
 
@@ -96,7 +97,7 @@ public final class KSMetaData
 
     public static KSMetaData newKeyspace(String name, Class<? extends AbstractReplicationStrategy>
strategyClass, Map<String, String> options, boolean durablesWrites, Iterable<CFMetaData>
cfDefs)
     {
-        return new KSMetaData(name, strategyClass, options, durablesWrites, cfDefs, new UTMetaData(),
Functions.none());
+        return new KSMetaData(name, strategyClass, options, durablesWrites, cfDefs, Types.none(),
Functions.none());
     }
 
     public KSMetaData cloneWithTableRemoved(CFMetaData table)
@@ -105,7 +106,7 @@ public final class KSMetaData
         List<CFMetaData> newTables = new ArrayList<>(cfMetaData().values());
         newTables.remove(table);
         assert newTables.size() == cfMetaData().size() - 1;
-        return cloneWith(newTables, userTypes, functions);
+        return cloneWith(newTables, types, functions);
     }
 
     public KSMetaData cloneWithTableAdded(CFMetaData table)
@@ -114,17 +115,22 @@ public final class KSMetaData
         List<CFMetaData> newTables = new ArrayList<>(cfMetaData().values());
         newTables.add(table);
         assert newTables.size() == cfMetaData().size() + 1;
-        return cloneWith(newTables, userTypes, functions);
+        return cloneWith(newTables, types, functions);
     }
 
-    public KSMetaData cloneWith(Iterable<CFMetaData> tables, UTMetaData types, Functions
functions)
+    public KSMetaData cloneWith(Iterable<CFMetaData> tables, Types types, Functions
functions)
     {
         return new KSMetaData(name, strategyClass, strategyOptions, durableWrites, tables,
types, functions);
     }
 
+    public KSMetaData cloneWith(Types types)
+    {
+        return new KSMetaData(name, strategyClass, strategyOptions, durableWrites, cfMetaData.values(),
types, functions);
+    }
+
     public KSMetaData cloneWith(Functions functions)
     {
-        return new KSMetaData(name, strategyClass, strategyOptions, durableWrites, cfMetaData.values(),
userTypes, functions);
+        return new KSMetaData(name, strategyClass, strategyOptions, durableWrites, cfMetaData.values(),
types, functions);
     }
 
     public static KSMetaData testMetadata(String name, Class<? extends AbstractReplicationStrategy>
strategyClass, Map<String, String> strategyOptions, CFMetaData... cfDefs)
@@ -140,7 +146,7 @@ public final class KSMetaData
     @Override
     public int hashCode()
     {
-        return Objects.hashCode(name, strategyClass, strategyOptions, cfMetaData, durableWrites,
functions, userTypes);
+        return Objects.hashCode(name, strategyClass, strategyOptions, cfMetaData, durableWrites,
functions, types);
     }
 
     @Override
@@ -160,7 +166,7 @@ public final class KSMetaData
             && Objects.equal(cfMetaData, other.cfMetaData)
             && Objects.equal(durableWrites, other.durableWrites)
             && Objects.equal(functions, other.functions)
-            && Objects.equal(userTypes, other.userTypes);
+            && Objects.equal(types, other.types);
     }
 
     public Map<String, CFMetaData> cfMetaData()
@@ -178,7 +184,7 @@ public final class KSMetaData
                       .add("cfMetaData", cfMetaData)
                       .add("durableWrites", durableWrites)
                       .add("functions", functions)
-                      .add("userTypes", userTypes)
+                      .add("types", types)
                       .toString();
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/2f2b58da/src/java/org/apache/cassandra/config/Schema.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/Schema.java b/src/java/org/apache/cassandra/config/Schema.java
index 07684ad..ebf83a9 100644
--- a/src/java/org/apache/cassandra/config/Schema.java
+++ b/src/java/org/apache/cassandra/config/Schema.java
@@ -453,10 +453,9 @@ public class Schema
     {
         KSMetaData oldKsm = getKSMetaData(ksName);
         assert oldKsm != null;
-        KSMetaData newKsm = LegacySchemaTables.createKeyspaceFromName(ksName).cloneWith(oldKsm.cfMetaData().values(),
oldKsm.userTypes, oldKsm.functions);
-
+        KSMetaData newKsm = LegacySchemaTables.createKeyspaceFromName(ksName)
+                                              .cloneWith(oldKsm.cfMetaData().values(), oldKsm.types,
oldKsm.functions);
         setKeyspaceDefinition(newKsm);
-
         Keyspace.open(ksName).createReplicationStrategy(newKsm);
         MigrationManager.instance.notifyUpdateKeyspace(newKsm);
     }
@@ -551,35 +550,28 @@ public class Schema
 
     public void addType(UserType ut)
     {
-        KSMetaData ksm = getKSMetaData(ut.keyspace);
-        assert ksm != null;
-
-        logger.info("Loading {}", ut);
-
-        ksm.userTypes.addType(ut);
-
+        KSMetaData oldKsm = getKSMetaData(ut.keyspace);
+        assert oldKsm != null;
+        KSMetaData newKsm = oldKsm.cloneWith(oldKsm.types.with(ut));
+        setKeyspaceDefinition(newKsm);
         MigrationManager.instance.notifyCreateUserType(ut);
     }
 
     public void updateType(UserType ut)
     {
-        KSMetaData ksm = getKSMetaData(ut.keyspace);
-        assert ksm != null;
-
-        logger.info("Updating {}", ut);
-
-        ksm.userTypes.addType(ut);
-
+        KSMetaData oldKsm = getKSMetaData(ut.keyspace);
+        assert oldKsm != null;
+        KSMetaData newKsm = oldKsm.cloneWith(oldKsm.types.without(ut.name).with(ut));
+        setKeyspaceDefinition(newKsm);
         MigrationManager.instance.notifyUpdateUserType(ut);
     }
 
     public void dropType(UserType ut)
     {
-        KSMetaData ksm = getKSMetaData(ut.keyspace);
-        assert ksm != null;
-
-        ksm.userTypes.removeType(ut);
-
+        KSMetaData oldKsm = getKSMetaData(ut.keyspace);
+        assert oldKsm != null;
+        KSMetaData newKsm = oldKsm.cloneWith(oldKsm.types.without(ut.name));
+        setKeyspaceDefinition(newKsm);
         MigrationManager.instance.notifyDropUserType(ut);
     }
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/2f2b58da/src/java/org/apache/cassandra/config/UTMetaData.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/config/UTMetaData.java b/src/java/org/apache/cassandra/config/UTMetaData.java
deleted file mode 100644
index 08cedee..0000000
--- a/src/java/org/apache/cassandra/config/UTMetaData.java
+++ /dev/null
@@ -1,76 +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 java.nio.ByteBuffer;
-import java.util.*;
-
-import org.apache.cassandra.db.marshal.*;
-
-/**
- * Defined (and loaded) user types.
- *
- * In practice, because user types are global, we have only one instance of
- * this class that retrieve through the Schema class.
- */
-public final class UTMetaData
-{
-    private final Map<ByteBuffer, UserType> userTypes;
-
-    public UTMetaData()
-    {
-        this(new HashMap<ByteBuffer, UserType>());
-    }
-
-    public UTMetaData(Map<ByteBuffer, UserType> types)
-    {
-        this.userTypes = types;
-    }
-
-    public UserType getType(ByteBuffer typeName)
-    {
-        return userTypes.get(typeName);
-    }
-
-    public Map<ByteBuffer, UserType> getAllTypes()
-    {
-        // Copy to avoid concurrent modification while iterating. Not intended to be called
on a critical path anyway
-        return new HashMap<>(userTypes);
-    }
-
-    // This is *not* thread safe but is only called in Schema that is synchronized.
-    public void addType(UserType type)
-    {
-        UserType old = userTypes.get(type.name);
-        assert old == null || type.isCompatibleWith(old);
-        userTypes.put(type.name, type);
-    }
-
-    // Same remarks than for addType
-    public void removeType(UserType type)
-    {
-        userTypes.remove(type.name);
-    }
-
-    public boolean equals(Object that)
-    {
-        if (!(that instanceof UTMetaData))
-            return false;
-        return userTypes.equals(((UTMetaData) that).userTypes);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/2f2b58da/src/java/org/apache/cassandra/cql3/CQL3Type.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/CQL3Type.java b/src/java/org/apache/cassandra/cql3/CQL3Type.java
index 290f4cb..c24f6fe 100644
--- a/src/java/org/apache/cassandra/cql3/CQL3Type.java
+++ b/src/java/org/apache/cassandra/cql3/CQL3Type.java
@@ -528,7 +528,7 @@ public interface CQL3Type
                 KSMetaData ksm = Schema.instance.getKSMetaData(name.getKeyspace());
                 if (ksm == null)
                     throw new InvalidRequestException("Unknown keyspace " + name.getKeyspace());
-                UserType type = ksm.userTypes.getType(name.getUserTypeName());
+                UserType type = ksm.types.getNullable(name.getUserTypeName());
                 if (type == null)
                     throw new InvalidRequestException("Unknown type " + name);
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/2f2b58da/src/java/org/apache/cassandra/cql3/functions/UDFunction.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/functions/UDFunction.java b/src/java/org/apache/cassandra/cql3/functions/UDFunction.java
index 77e4afe..14a8ff2 100644
--- a/src/java/org/apache/cassandra/cql3/functions/UDFunction.java
+++ b/src/java/org/apache/cassandra/cql3/functions/UDFunction.java
@@ -295,7 +295,7 @@ public abstract class UDFunction extends AbstractFunction implements ScalarFunct
                     KSMetaData ksm = Schema.instance.getKSMetaData(ksName);
                     assert ksm != null;
 
-                    org.apache.cassandra.db.marshal.UserType ut = ksm.userTypes.getType(ByteBufferUtil.bytes(typeName));
+                    org.apache.cassandra.db.marshal.UserType ut = ksm.types.get(ByteBufferUtil.bytes(typeName)).get();
 
                     DataType newUserType = UDHelper.driverType(ut);
                     argDataTypes[i] = newUserType;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/2f2b58da/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 4e78bfc..0fb084e 100644
--- a/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/AlterTypeStatement.java
@@ -95,10 +95,9 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement
         if (ksm == null)
             throw new InvalidRequestException(String.format("Cannot alter type in unknown
keyspace %s", name.getKeyspace()));
 
-        UserType toUpdate = ksm.userTypes.getType(name.getUserTypeName());
-        // Shouldn't happen, unless we race with a drop
-        if (toUpdate == null)
-            throw new InvalidRequestException(String.format("No user type named %s exists.",
name));
+        UserType toUpdate =
+            ksm.types.get(name.getUserTypeName())
+                     .orElseThrow(() -> new InvalidRequestException(String.format("No
user type named %s exists.", name)));
 
         UserType updated = makeUpdatedType(toUpdate);
 
@@ -117,7 +116,7 @@ public abstract class AlterTypeStatement extends SchemaAlteringStatement
         }
 
         // Other user types potentially using the updated type
-        for (UserType ut : ksm.userTypes.getAllTypes().values())
+        for (UserType ut : ksm.types)
         {
             // Re-updating the type we've just updated would be harmless but useless so we
avoid it.
             // Besides, we use the occasion to drop the old version of the type if it's a
type rename

http://git-wip-us.apache.org/repos/asf/cassandra/blob/2f2b58da/src/java/org/apache/cassandra/cql3/statements/CreateTypeStatement.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/cql3/statements/CreateTypeStatement.java b/src/java/org/apache/cassandra/cql3/statements/CreateTypeStatement.java
index 82c2808..97f3ed6 100644
--- a/src/java/org/apache/cassandra/cql3/statements/CreateTypeStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/CreateTypeStatement.java
@@ -69,7 +69,7 @@ public class CreateTypeStatement extends SchemaAlteringStatement
         if (ksm == null)
             throw new InvalidRequestException(String.format("Cannot add type in unknown keyspace
%s", name.getKeyspace()));
 
-        if (ksm.userTypes.getType(name.getUserTypeName()) != null && !ifNotExists)
+        if (ksm.types.get(name.getUserTypeName()).isPresent() && !ifNotExists)
             throw new InvalidRequestException(String.format("A user type of name %s already
exists", name));
 
         for (CQL3Type.Raw type : columnTypes)
@@ -122,7 +122,7 @@ public class CreateTypeStatement extends SchemaAlteringStatement
         assert ksm != null; // should haven't validate otherwise
 
         // Can happen with ifNotExists
-        if (ksm.userTypes.getType(name.getUserTypeName()) != null)
+        if (ksm.types.get(name.getUserTypeName()).isPresent())
             return false;
 
         UserType type = createType();

http://git-wip-us.apache.org/repos/asf/cassandra/blob/2f2b58da/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 5edac58..ddb0959 100644
--- a/src/java/org/apache/cassandra/cql3/statements/DropTypeStatement.java
+++ b/src/java/org/apache/cassandra/cql3/statements/DropTypeStatement.java
@@ -57,8 +57,7 @@ public class DropTypeStatement extends SchemaAlteringStatement
         if (ksm == null)
             throw new InvalidRequestException(String.format("Cannot drop type in unknown
keyspace %s", name.getKeyspace()));
 
-        UserType old = ksm.userTypes.getType(name.getUserTypeName());
-        if (old == null)
+        if (!ksm.types.get(name.getUserTypeName()).isPresent())
         {
             if (ifExists)
                 return;
@@ -83,7 +82,7 @@ public class DropTypeStatement extends SchemaAlteringStatement
                     throw new InvalidRequestException(String.format("Cannot drop user type
%s as it is still used by function %s", name, function));
         }
 
-        for (UserType ut : ksm.userTypes.getAllTypes().values())
+        for (UserType ut : ksm.types)
             if (!ut.name.equals(name.getUserTypeName()) && isUsedBy(ut))
                 throw new InvalidRequestException(String.format("Cannot drop user type %s
as it is still used by user type %s", name, ut.asCQL3Type()));
 
@@ -140,7 +139,7 @@ public class DropTypeStatement extends SchemaAlteringStatement
         KSMetaData ksm = Schema.instance.getKSMetaData(name.getKeyspace());
         assert ksm != null;
 
-        UserType toDrop = ksm.userTypes.getType(name.getUserTypeName());
+        UserType toDrop = ksm.types.getNullable(name.getUserTypeName());
         // Can be null with ifExists
         if (toDrop == null)
             return false;

http://git-wip-us.apache.org/repos/asf/cassandra/blob/2f2b58da/src/java/org/apache/cassandra/schema/LegacySchemaTables.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/schema/LegacySchemaTables.java b/src/java/org/apache/cassandra/schema/LegacySchemaTables.java
index 42c67db..4077700 100644
--- a/src/java/org/apache/cassandra/schema/LegacySchemaTables.java
+++ b/src/java/org/apache/cassandra/schema/LegacySchemaTables.java
@@ -661,8 +661,8 @@ public final class LegacySchemaTables
 
         if (withTablesAndTypesAndFunctions)
         {
-            keyspace.userTypes.getAllTypes().values().forEach(type -> addTypeToSchemaMutation(type,
timestamp, mutation));
             keyspace.cfMetaData().values().forEach(table -> addTableToSchemaMutation(table,
timestamp, true, mutation));
+            keyspace.types.forEach(type -> addTypeToSchemaMutation(type, timestamp, mutation));
             keyspace.functions.udfs().forEach(udf -> addFunctionToSchemaMutation(udf,
timestamp, mutation));
             keyspace.functions.udas().forEach(uda -> addAggregateToSchemaMutation(uda,
timestamp, mutation));
         }
@@ -687,12 +687,10 @@ public final class LegacySchemaTables
                                                                  RowIterator seriazliedAggregates)
     {
         Collection<CFMetaData> tables = createTablesFromTablesPartition(serializedTables);
-        UTMetaData types = new UTMetaData(createTypesFromPartition(serializedTypes));
-
+        Types types = createTypesFromPartition(serializedTypes);
         Collection<UDFunction> udfs = createFunctionsFromFunctionsPartition(serializedFunctions);
         Collection<UDAggregate> udas = createAggregatesFromAggregatesPartition(seriazliedAggregates);
         Functions functions = org.apache.cassandra.schema.Functions.builder().add(udfs).add(udas).build();
-
         return createKeyspaceFromSchemaPartition(serializedKeyspace).cloneWith(tables, types,
functions);
     }
 
@@ -759,16 +757,12 @@ public final class LegacySchemaTables
         return RowUpdateBuilder.deleteRow(Usertypes, timestamp, mutation, type.name);
     }
 
-    private static Map<ByteBuffer, UserType> createTypesFromPartition(RowIterator partition)
+    private static Types createTypesFromPartition(RowIterator partition)
     {
         String query = String.format("SELECT * FROM %s.%s", SystemKeyspace.NAME, USERTYPES);
-        Map<ByteBuffer, UserType> types = new HashMap<>();
-        for (UntypedResultSet.Row row : QueryProcessor.resultify(query, partition))
-        {
-            UserType type = createTypeFromRow(row);
-            types.put(type.name, type);
-        }
-        return types;
+        Types.Builder types = Types.builder();
+        QueryProcessor.resultify(query, partition).forEach(row -> types.add(createTypeFromRow(row)));
+        return types.build();
     }
 
     private static UserType createTypeFromRow(UntypedResultSet.Row row)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/2f2b58da/src/java/org/apache/cassandra/schema/Types.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/schema/Types.java b/src/java/org/apache/cassandra/schema/Types.java
new file mode 100644
index 0000000..982e3f5
--- /dev/null
+++ b/src/java/org/apache/cassandra/schema/Types.java
@@ -0,0 +1,147 @@
+/*
+ * 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.nio.ByteBuffer;
+import java.util.Iterator;
+import java.util.Optional;
+
+import javax.annotation.Nullable;
+
+import com.google.common.collect.ImmutableMap;
+
+import org.apache.cassandra.db.marshal.UserType;
+
+import static com.google.common.collect.Iterables.filter;
+
+/**
+ * An immutable container for a keyspace's UDTs.
+ */
+public final class Types implements Iterable<UserType>
+{
+    private final ImmutableMap<ByteBuffer, UserType> types;
+
+    private Types(Builder builder)
+    {
+        types = builder.types.build();
+    }
+
+    public static Builder builder()
+    {
+        return new Builder();
+    }
+
+    public static Types none()
+    {
+        return builder().build();
+    }
+
+    public Iterator<UserType> iterator()
+    {
+        return types.values().iterator();
+    }
+
+    /**
+     * Get the type with the specified name
+     *
+     * @param name a non-qualified type name
+     * @return an empty {@link Optional} if the type name is not found; a non-empty optional
of {@link UserType} otherwise
+     */
+    public Optional<UserType> get(ByteBuffer name)
+    {
+        return Optional.ofNullable(types.get(name));
+    }
+
+    /**
+     * Get the type with the specified name
+     *
+     * @param name a non-qualified type name
+     * @return null if the type name is not found; the found {@link UserType} otherwise
+     */
+    @Nullable
+    public UserType getNullable(ByteBuffer name)
+    {
+        return types.get(name);
+    }
+
+    /**
+     * Create a Types instance with the provided type added
+     */
+    public Types with(UserType type)
+    {
+        if (get(type.name).isPresent())
+            throw new IllegalStateException(String.format("Type %s already exists", type.name));
+
+        return builder().add(this).add(type).build();
+    }
+
+    /**
+     * Creates a Types instance with the type with the provided name removed
+     */
+    public Types without(ByteBuffer name)
+    {
+        UserType type =
+            get(name).orElseThrow(() -> new IllegalStateException(String.format("Type
%s doesn't exists", name)));
+
+        return builder().add(filter(this, t -> t != type)).build();
+    }
+
+    @Override
+    public boolean equals(Object o)
+    {
+        return this == o || (o instanceof Types && types.equals(((Types) o).types));
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return types.hashCode();
+    }
+
+    @Override
+    public String toString()
+    {
+        return types.values().toString();
+    }
+
+    public static final class Builder
+    {
+        final ImmutableMap.Builder<ByteBuffer, UserType> types = new ImmutableMap.Builder<>();
+
+        private Builder()
+        {
+        }
+
+        public Types build()
+        {
+            return new Types(this);
+        }
+
+        public Builder add(UserType type)
+        {
+            types.put(type.name, type);
+            return this;
+        }
+
+        public Builder add(Iterable<UserType> types)
+        {
+            types.forEach(this::add);
+            return this;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/2f2b58da/test/unit/org/apache/cassandra/cql3/selection/SelectionColumnMappingTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/selection/SelectionColumnMappingTest.java
b/test/unit/org/apache/cassandra/cql3/selection/SelectionColumnMappingTest.java
index 2f1d361..971176a 100644
--- a/test/unit/org/apache/cassandra/cql3/selection/SelectionColumnMappingTest.java
+++ b/test/unit/org/apache/cassandra/cql3/selection/SelectionColumnMappingTest.java
@@ -46,7 +46,7 @@ public class SelectionColumnMappingTest extends CQLTester
                                     " v1 int," +
                                     " v2 ascii," +
                                     " v3 frozen<" + typeName + ">)");
-        userType = Schema.instance.getKSMetaData(KEYSPACE).userTypes.getType(ByteBufferUtil.bytes(typeName));
+        userType = Schema.instance.getKSMetaData(KEYSPACE).types.get(ByteBufferUtil.bytes(typeName)).get();
         functionName = createFunction(KEYSPACE, "int, ascii",
                                       "CREATE FUNCTION %s (i int, a ascii) " +
                                       "CALLED ON NULL INPUT " +


Mime
View raw message