cassandra-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From alek...@apache.org
Subject [1/4] cassandra git commit: Move schema tables to the new system_schema keyspace
Date Fri, 10 Jul 2015 12:29:05 GMT
Repository: cassandra
Updated Branches:
  refs/heads/trunk 81ba56163 -> 7d6c876ec


http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/src/java/org/apache/cassandra/service/StorageService.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java
index 93f69a9..596e463 100644
--- a/src/java/org/apache/cassandra/service/StorageService.java
+++ b/src/java/org/apache/cassandra/service/StorageService.java
@@ -2471,7 +2471,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
 
     public int forceKeyspaceCleanup(String keyspaceName, String... columnFamilies) throws IOException, ExecutionException, InterruptedException
     {
-        if (keyspaceName.equals(SystemKeyspace.NAME))
+        if (Schema.isSystemKeyspace(keyspaceName))
             throw new RuntimeException("Cleanup of the system keyspace is neither necessary nor wise");
 
         CompactionManager.AllSSTableOpStatus status = CompactionManager.AllSSTableOpStatus.SUCCESSFUL;
@@ -2705,7 +2705,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
         Map<String, TabularData> snapshotMap = new HashMap<>();
         for (Keyspace keyspace : Keyspace.all())
         {
-            if (SystemKeyspace.NAME.equals(keyspace.getName()))
+            if (Schema.isSystemKeyspace(keyspace.getName()))
                 continue;
 
             for (ColumnFamilyStore cfStore : keyspace.getColumnFamilyStores())
@@ -2731,7 +2731,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
         long total = 0;
         for (Keyspace keyspace : Keyspace.all())
         {
-            if (SystemKeyspace.NAME.equals(keyspace.getName()))
+            if (Schema.isSystemKeyspace(keyspace.getName()))
                 continue;
 
             for (ColumnFamilyStore cfStore : keyspace.getColumnFamilyStores())

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/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 f60ea48..3e0c8f4 100644
--- a/src/java/org/apache/cassandra/thrift/ThriftConversion.java
+++ b/src/java/org/apache/cassandra/thrift/ThriftConversion.java
@@ -40,9 +40,9 @@ import org.apache.cassandra.locator.AbstractReplicationStrategy;
 import org.apache.cassandra.locator.LocalStrategy;
 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.serializers.MarshalException;
-import org.apache.cassandra.schema.LegacySchemaTables;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.UUIDGen;
 
@@ -414,7 +414,7 @@ public class ThriftConversion
             cols.add(convertThriftCqlRow(row));
         UntypedResultSet colsRows = UntypedResultSet.create(cols);
 
-        return LegacySchemaTables.createTableFromTableRowAndColumnRows(cfRow, colsRows);
+        return SchemaKeyspace.createTableFromTableRowAndColumnRows(cfRow, colsRows);
     }
 
     private static Map<String, ByteBuffer> convertThriftCqlRow(CqlRow row)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/src/java/org/apache/cassandra/thrift/ThriftValidation.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/thrift/ThriftValidation.java b/src/java/org/apache/cassandra/thrift/ThriftValidation.java
index dd5bf98..13c55aa 100644
--- a/src/java/org/apache/cassandra/thrift/ThriftValidation.java
+++ b/src/java/org/apache/cassandra/thrift/ThriftValidation.java
@@ -632,8 +632,8 @@ public class ThriftValidation
 
     public static void validateKeyspaceNotSystem(String modifiedKeyspace) throws org.apache.cassandra.exceptions.InvalidRequestException
     {
-        if (modifiedKeyspace.equalsIgnoreCase(SystemKeyspace.NAME))
-            throw new org.apache.cassandra.exceptions.InvalidRequestException("system keyspace is not user-modifiable");
+        if (Schema.isSystemKeyspace(modifiedKeyspace))
+            throw new org.apache.cassandra.exceptions.InvalidRequestException(String.format("%s keyspace is not user-modifiable", modifiedKeyspace));
     }
 
     //public static IDiskAtomFilter asIFilter(SlicePredicate sp, CFMetaData metadata, ByteBuffer superColumn)

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/src/java/org/apache/cassandra/tools/nodetool/Cleanup.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/tools/nodetool/Cleanup.java b/src/java/org/apache/cassandra/tools/nodetool/Cleanup.java
index aa415b3..d5c505e 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/Cleanup.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/Cleanup.java
@@ -23,6 +23,7 @@ import io.airlift.command.Command;
 import java.util.ArrayList;
 import java.util.List;
 
+import org.apache.cassandra.config.Schema;
 import org.apache.cassandra.db.SystemKeyspace;
 import org.apache.cassandra.tools.NodeProbe;
 import org.apache.cassandra.tools.NodeTool.NodeToolCmd;
@@ -41,13 +42,14 @@ public class Cleanup extends NodeToolCmd
 
         for (String keyspace : keyspaces)
         {
-            if (SystemKeyspace.NAME.equals(keyspace))
+            if (Schema.isSystemKeyspace(keyspace))
                 continue;
 
             try
             {
                 probe.forceKeyspaceCleanup(System.out, keyspace, cfnames);
-            } catch (Exception e)
+            }
+            catch (Exception e)
             {
                 throw new RuntimeException("Error occurred during cleanup", e);
             }

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java
----------------------------------------------------------------------
diff --git a/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java b/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java
index f2663bf..fa415ae 100644
--- a/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java
+++ b/src/java/org/apache/cassandra/utils/NativeSSTableLoaderClient.java
@@ -26,12 +26,11 @@ import org.apache.cassandra.config.ColumnDefinition;
 import org.apache.cassandra.config.CFMetaData;
 import org.apache.cassandra.cql3.ColumnIdentifier;
 import org.apache.cassandra.db.CompactTables;
-import org.apache.cassandra.db.SystemKeyspace;
 import org.apache.cassandra.db.marshal.*;
 import org.apache.cassandra.dht.*;
 import org.apache.cassandra.dht.Token;
 import org.apache.cassandra.io.sstable.SSTableLoader;
-import org.apache.cassandra.schema.LegacySchemaTables;
+import org.apache.cassandra.schema.SchemaKeyspace;
 
 public class NativeSSTableLoaderClient extends SSTableLoader.Client
 {
@@ -100,9 +99,9 @@ public class NativeSSTableLoaderClient extends SSTableLoader.Client
     {
         Map<String, CFMetaData> tables = new HashMap<>();
 
-        String query = String.format("SELECT columnfamily_name, cf_id, type, comparator, subcomparator, is_dense, default_validator FROM %s.%s WHERE keyspace_name = '%s'",
-                                     SystemKeyspace.NAME,
-                                     LegacySchemaTables.COLUMNFAMILIES,
+        String query = String.format("SELECT table_name, cf_id, type, comparator, subcomparator, is_dense, default_validator FROM %s.%s WHERE keyspace_name = '%s'",
+                                     SchemaKeyspace.NAME,
+                                     SchemaKeyspace.TABLES,
                                      keyspace);
 
 
@@ -110,7 +109,7 @@ public class NativeSSTableLoaderClient extends SSTableLoader.Client
         // be safer to have a simple wrapper of the driver ResultSet/Row implementing UntypedResultSet/UntypedResultSet.Row and reuse the original method.
         for (Row row : session.execute(query))
         {
-            String name = row.getString("columnfamily_name");
+            String name = row.getString("table_name");
             UUID id = row.getUUID("cf_id");
             boolean isSuper = row.getString("type").toLowerCase().equals("super");
             AbstractType rawComparator = TypeParser.parse(row.getString("comparator"));
@@ -124,9 +123,9 @@ public class NativeSSTableLoaderClient extends SSTableLoader.Client
             boolean isCounter =  defaultValidator instanceof CounterColumnType;
             boolean isCQLTable = !isSuper && !isDense && isCompound;
 
-            String columnsQuery = String.format("SELECT column_name, component_index, type, validator FROM %s.%s WHERE keyspace_name='%s' AND columnfamily_name='%s'",
-                                                SystemKeyspace.NAME,
-                                                LegacySchemaTables.COLUMNS,
+            String columnsQuery = String.format("SELECT column_name, component_index, type, validator FROM %s.%s WHERE keyspace_name='%s' AND table_name='%s'",
+                                                SchemaKeyspace.NAME,
+                                                SchemaKeyspace.COLUMNS,
                                                 keyspace,
                                                 name);
 
@@ -149,7 +148,7 @@ public class NativeSSTableLoaderClient extends SSTableLoader.Client
                                                             boolean isSuper,
                                                             boolean isCQLTable)
     {
-        ColumnDefinition.Kind kind = LegacySchemaTables.deserializeKind(row.getString("type"));
+        ColumnDefinition.Kind kind = SchemaKeyspace.deserializeKind(row.getString("type"));
 
         Integer componentIndex = null;
         if (!row.isNull("component_index"))

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/SchemaLoader.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/SchemaLoader.java b/test/unit/org/apache/cassandra/SchemaLoader.java
index bd213a5..86e4762 100644
--- a/test/unit/org/apache/cassandra/SchemaLoader.java
+++ b/test/unit/org/apache/cassandra/SchemaLoader.java
@@ -143,7 +143,7 @@ public class SchemaLoader
                 //CFMetaData.Builder.create(ks1, "Counter1", false, false, true).build(),
                 //CFMetaData.Builder.create(ks1, "SuperCounter1", false, false, true, true).build(),
                 superCFMD(ks1, "SuperDirectGC", BytesType.instance).gcGraceSeconds(0),
-                jdbcCFMD(ks1, "JdbcInteger", IntegerType.instance).addColumnDefinition(integerColumn(ks1, "JdbcInteger")),
+//                jdbcCFMD(ks1, "JdbcInteger", IntegerType.instance).addColumnDefinition(integerColumn(ks1, "JdbcInteger")),
                 jdbcCFMD(ks1, "JdbcUtf8", UTF8Type.instance).addColumnDefinition(utf8Column(ks1, "JdbcUtf8")),
                 jdbcCFMD(ks1, "JdbcLong", LongType.instance),
                 jdbcCFMD(ks1, "JdbcBytes", bytes),
@@ -296,7 +296,7 @@ public class SchemaLoader
                                     ColumnDefinition.Kind.REGULAR);
     }
 
-    private static ColumnDefinition utf8Column(String ksName, String cfName)
+    public static ColumnDefinition utf8Column(String ksName, String cfName)
     {
         return new ColumnDefinition(ksName,
                                     cfName,

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/config/CFMetaDataTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/config/CFMetaDataTest.java b/test/unit/org/apache/cassandra/config/CFMetaDataTest.java
index 1238464..c0808d2 100644
--- a/test/unit/org/apache/cassandra/config/CFMetaDataTest.java
+++ b/test/unit/org/apache/cassandra/config/CFMetaDataTest.java
@@ -33,7 +33,7 @@ import org.apache.cassandra.exceptions.ConfigurationException;
 import org.apache.cassandra.io.compress.*;
 import org.apache.cassandra.schema.KeyspaceMetadata;
 import org.apache.cassandra.schema.KeyspaceParams;
-import org.apache.cassandra.schema.LegacySchemaTables;
+import org.apache.cassandra.schema.SchemaKeyspace;
 import org.apache.cassandra.service.StorageService;
 import org.apache.cassandra.thrift.CfDef;
 import org.apache.cassandra.thrift.ColumnDef;
@@ -143,10 +143,10 @@ public class CFMetaDataTest
         assert before.equals(after) : String.format("%n%s%n!=%n%s", before, after);
 
         // Test schema conversion
-        Mutation rm = LegacySchemaTables.makeCreateTableMutation(keyspace, cfm, FBUtilities.timestampMicros());
-        PartitionUpdate cfU = rm.getPartitionUpdate(Schema.instance.getId(SystemKeyspace.NAME, LegacySchemaTables.COLUMNFAMILIES));
-        PartitionUpdate cdU = rm.getPartitionUpdate(Schema.instance.getId(SystemKeyspace.NAME, LegacySchemaTables.COLUMNS));
-        CFMetaData newCfm = LegacySchemaTables.createTableFromTablePartitionAndColumnsPartition(
+        Mutation rm = SchemaKeyspace.makeCreateTableMutation(keyspace, cfm, FBUtilities.timestampMicros());
+        PartitionUpdate cfU = rm.getPartitionUpdate(Schema.instance.getId(SchemaKeyspace.NAME, SchemaKeyspace.TABLES));
+        PartitionUpdate cdU = rm.getPartitionUpdate(Schema.instance.getId(SchemaKeyspace.NAME, SchemaKeyspace.COLUMNS));
+        CFMetaData newCfm = SchemaKeyspace.createTableFromTablePartitionAndColumnsPartition(
                 UnfilteredRowIterators.filter(cfU.unfilteredIterator(), FBUtilities.nowInSeconds()),
                 UnfilteredRowIterators.filter(cdU.unfilteredIterator(), FBUtilities.nowInSeconds())
         );

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/config/LegacySchemaTablesTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/config/LegacySchemaTablesTest.java b/test/unit/org/apache/cassandra/config/LegacySchemaTablesTest.java
deleted file mode 100644
index aabc392..0000000
--- a/test/unit/org/apache/cassandra/config/LegacySchemaTablesTest.java
+++ /dev/null
@@ -1,153 +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.util.ArrayList;
-import java.util.List;
-import java.util.HashMap;
-import java.util.HashSet;
-
-import org.apache.cassandra.SchemaLoader;
-import org.apache.cassandra.db.*;
-import org.apache.cassandra.db.rows.UnfilteredRowIterators;
-import org.apache.cassandra.db.partitions.PartitionUpdate;
-import org.apache.cassandra.db.marshal.AsciiType;
-import org.apache.cassandra.db.marshal.UTF8Type;
-import org.apache.cassandra.exceptions.ConfigurationException;
-import org.apache.cassandra.io.compress.*;
-import org.apache.cassandra.schema.KeyspaceMetadata;
-import org.apache.cassandra.schema.KeyspaceParams;
-import org.apache.cassandra.schema.LegacySchemaTables;
-import org.apache.cassandra.service.StorageService;
-import org.apache.cassandra.thrift.CfDef;
-import org.apache.cassandra.thrift.ColumnDef;
-import org.apache.cassandra.thrift.IndexType;
-import org.apache.cassandra.thrift.ThriftConversion;
-import org.apache.cassandra.utils.ByteBufferUtil;
-import org.apache.cassandra.utils.FBUtilities;
-
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class LegacySchemaTablesTest
-{
-    private static final String KEYSPACE1 = "CFMetaDataTest1";
-    private static final String CF_STANDARD1 = "Standard1";
-
-    private static List<ColumnDef> columnDefs = new ArrayList<ColumnDef>();
-
-    static
-    {
-        columnDefs.add(new ColumnDef(ByteBufferUtil.bytes("col1"), AsciiType.class.getCanonicalName())
-                                    .setIndex_name("col1Index")
-                                    .setIndex_type(IndexType.KEYS));
-
-        columnDefs.add(new ColumnDef(ByteBufferUtil.bytes("col2"), UTF8Type.class.getCanonicalName())
-                                    .setIndex_name("col2Index")
-                                    .setIndex_type(IndexType.KEYS));
-    }
-
-    @BeforeClass
-    public static void defineSchema() throws ConfigurationException
-    {
-        SchemaLoader.prepareServer();
-        SchemaLoader.createKeyspace(KEYSPACE1,
-                                    KeyspaceParams.simple(1),
-                                    SchemaLoader.standardCFMD(KEYSPACE1, CF_STANDARD1));
-    }
-
-    @Test
-    public void testThriftConversion() throws Exception
-    {
-        CfDef cfDef = new CfDef().setDefault_validation_class(AsciiType.class.getCanonicalName())
-                                 .setComment("Test comment")
-                                 .setColumn_metadata(columnDefs)
-                                 .setKeyspace(KEYSPACE1)
-                                 .setName(CF_STANDARD1);
-
-        // convert Thrift to CFMetaData
-        CFMetaData cfMetaData = ThriftConversion.fromThrift(cfDef);
-
-        CfDef thriftCfDef = new CfDef();
-        thriftCfDef.keyspace = KEYSPACE1;
-        thriftCfDef.name = CF_STANDARD1;
-        thriftCfDef.default_validation_class = cfDef.default_validation_class;
-        thriftCfDef.comment = cfDef.comment;
-        thriftCfDef.column_metadata = new ArrayList<>();
-        for (ColumnDef columnDef : columnDefs)
-        {
-            ColumnDef c = new ColumnDef();
-            c.name = ByteBufferUtil.clone(columnDef.name);
-            c.validation_class = columnDef.getValidation_class();
-            c.index_name = columnDef.getIndex_name();
-            c.index_type = IndexType.KEYS;
-            thriftCfDef.column_metadata.add(c);
-        }
-
-        CfDef converted = ThriftConversion.toThrift(cfMetaData);
-
-        assertEquals(thriftCfDef.keyspace, converted.keyspace);
-        assertEquals(thriftCfDef.name, converted.name);
-        assertEquals(thriftCfDef.default_validation_class, converted.default_validation_class);
-        assertEquals(thriftCfDef.comment, converted.comment);
-        assertEquals(new HashSet<>(thriftCfDef.column_metadata), new HashSet<>(converted.column_metadata));
-    }
-
-    @Test
-    public void testConversionsInverses() throws Exception
-    {
-        for (String keyspaceName : Schema.instance.getNonSystemKeyspaces())
-        {
-            for (ColumnFamilyStore cfs : Keyspace.open(keyspaceName).getColumnFamilyStores())
-            {
-                CFMetaData cfm = cfs.metadata;
-                if (!cfm.isThriftCompatible())
-                    continue;
-
-                checkInverses(cfm);
-
-                // Testing with compression to catch #3558
-                CFMetaData withCompression = cfm.copy();
-                withCompression.compressionParameters(new CompressionParameters(SnappyCompressor.instance, 32768, new HashMap<String, String>()));
-                checkInverses(withCompression);
-            }
-        }
-    }
-
-    private void checkInverses(CFMetaData cfm) throws Exception
-    {
-        DecoratedKey k = StorageService.getPartitioner().decorateKey(ByteBufferUtil.bytes(cfm.ksName));
-        KeyspaceMetadata keyspace = Schema.instance.getKSMetaData(cfm.ksName);
-
-        // Test thrift conversion
-        CFMetaData before = cfm;
-        CFMetaData after = ThriftConversion.fromThriftForUpdate(ThriftConversion.toThrift(before), before);
-        assert before.equals(after) : String.format("%n%s%n!=%n%s", before, after);
-
-        // Test schema conversion
-        Mutation rm = LegacySchemaTables.makeCreateTableMutation(keyspace, cfm, FBUtilities.timestampMicros());
-        PartitionUpdate serializedCf = rm.getPartitionUpdate(Schema.instance.getId(SystemKeyspace.NAME, LegacySchemaTables.COLUMNFAMILIES));
-        PartitionUpdate serializedCD = rm.getPartitionUpdate(Schema.instance.getId(SystemKeyspace.NAME, LegacySchemaTables.COLUMNS));
-        CFMetaData newCfm = LegacySchemaTables.createTableFromTablePartitionAndColumnsPartition(UnfilteredRowIterators.filter(serializedCf.unfilteredIterator(), FBUtilities.nowInSeconds()),
-                                                                                                UnfilteredRowIterators.filter(serializedCD.unfilteredIterator(), FBUtilities.nowInSeconds()));
-        assert cfm.equals(newCfm) : String.format("%n%s%n!=%n%s", cfm, newCfm);
-    }
-}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
index 4cf5abf..8c24cc5 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/entities/UFTest.java
@@ -115,12 +115,12 @@ public class UFTest extends CQLTester
 
         Assert.assertEquals(1, Schema.instance.getFunctions(parseFunctionName(fSin)).size());
 
-        assertRows(execute("SELECT function_name, language FROM system.schema_functions WHERE keyspace_name=?", KEYSPACE_PER_TEST),
+        assertRows(execute("SELECT function_name, language FROM system_schema.functions WHERE keyspace_name=?", KEYSPACE_PER_TEST),
                    row(fSinName.name, "java"));
 
         dropPerTestKeyspace();
 
-        assertRows(execute("SELECT function_name, language FROM system.schema_functions WHERE keyspace_name=?", KEYSPACE_PER_TEST));
+        assertRows(execute("SELECT function_name, language FROM system_schema.functions WHERE keyspace_name=?", KEYSPACE_PER_TEST));
 
         Assert.assertEquals(0, Schema.instance.getFunctions(fSinName).size());
     }
@@ -558,7 +558,7 @@ public class UFTest extends CQLTester
                                       "LANGUAGE JAVA\n" +
                                       "AS '" +functionBody + "';");
 
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
                            KEYSPACE, parseFunctionName(fName).name),
                    row("java", functionBody));
 
@@ -662,7 +662,7 @@ public class UFTest extends CQLTester
 
         FunctionName fNameName = parseFunctionName(fName);
 
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
                            fNameName.keyspace, fNameName.name),
                    row("java", functionBody));
 
@@ -825,7 +825,7 @@ public class UFTest extends CQLTester
 
         FunctionName fNameName = parseFunctionName(fName);
 
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
                            fNameName.keyspace, fNameName.name),
                    row("java", functionBody));
 
@@ -856,7 +856,7 @@ public class UFTest extends CQLTester
 
         FunctionName fNameName = parseFunctionName(fName);
 
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
                            fNameName.keyspace, fNameName.name),
                    row("java", functionBody));
 
@@ -889,7 +889,7 @@ public class UFTest extends CQLTester
 
         FunctionName fNameName = parseFunctionName(fName);
 
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
                            fNameName.keyspace, fNameName.name),
                    row("java", functionBody));
     }
@@ -1792,7 +1792,7 @@ public class UFTest extends CQLTester
 
         FunctionName fNameName = parseFunctionName(fName);
 
-        assertRows(execute("SELECT language, body FROM system.schema_functions WHERE keyspace_name=? AND function_name=?",
+        assertRows(execute("SELECT language, body FROM system_schema.functions WHERE keyspace_name=? AND function_name=?",
                            fNameName.keyspace, fNameName.name),
                    row("javascript", functionBody));
 

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java
index 05f6c35..66b6b33 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/AlterTest.java
@@ -17,6 +17,8 @@
  */
 package org.apache.cassandra.cql3.validation.operations;
 
+import com.google.common.collect.ImmutableMap;
+
 import org.apache.cassandra.cql3.CQLTester;
 import org.apache.cassandra.db.ColumnFamilyStore;
 import org.apache.cassandra.db.Keyspace;
@@ -129,7 +131,7 @@ public class AlterTest extends CQLTester
         execute("CREATE KEYSPACE ks1 WITH replication={ 'class' : 'SimpleStrategy', 'replication_factor' : 1 }");
         execute("CREATE KEYSPACE ks2 WITH replication={ 'class' : 'SimpleStrategy', 'replication_factor' : 1 } AND durable_writes=false");
 
-        assertRows(execute("SELECT keyspace_name, durable_writes FROM system.schema_keyspaces"),
+        assertRows(execute("SELECT keyspace_name, durable_writes FROM system_schema.keyspaces"),
                    row("ks1", true),
                    row(KEYSPACE, true),
                    row(KEYSPACE_PER_TEST, true),
@@ -138,18 +140,22 @@ public class AlterTest extends CQLTester
         execute("ALTER KEYSPACE ks1 WITH replication = { 'class' : 'NetworkTopologyStrategy', 'dc1' : 1 } AND durable_writes=False");
         execute("ALTER KEYSPACE ks2 WITH durable_writes=true");
 
-        assertRows(execute("SELECT keyspace_name, durable_writes, strategy_class FROM system.schema_keyspaces"),
-                   row("ks1", false, "org.apache.cassandra.locator.NetworkTopologyStrategy"),
-                   row(KEYSPACE, true, "org.apache.cassandra.locator.SimpleStrategy"),
-                   row(KEYSPACE_PER_TEST, true, "org.apache.cassandra.locator.SimpleStrategy"),
-                   row("ks2", true, "org.apache.cassandra.locator.SimpleStrategy"));
+        assertRows(execute("SELECT keyspace_name, durable_writes, replication FROM system_schema.keyspaces"),
+                   row("ks1", false, ImmutableMap.of("class", "org.apache.cassandra.locator.NetworkTopologyStrategy",
+                                                     "dc1", "1")),
+                   row(KEYSPACE, true, ImmutableMap.of("class", "org.apache.cassandra.locator.SimpleStrategy",
+                                                       "replication_factor", "1")),
+                   row(KEYSPACE_PER_TEST, true, ImmutableMap.of("class", "org.apache.cassandra.locator.SimpleStrategy",
+                                                                "replication_factor", "1")),
+                   row("ks2", true, ImmutableMap.of("class", "org.apache.cassandra.locator.SimpleStrategy",
+                                                    "replication_factor", "1")));
 
         execute("USE ks1");
 
         assertInvalidThrow(ConfigurationException.class, "CREATE TABLE cf1 (a int PRIMARY KEY, b int) WITH compaction = { 'min_threshold' : 4 }");
 
         execute("CREATE TABLE cf1 (a int PRIMARY KEY, b int) WITH compaction = { 'class' : 'SizeTieredCompactionStrategy', 'min_threshold' : 7 }");
-        assertRows(execute("SELECT columnfamily_name, min_compaction_threshold FROM system.schema_columnfamilies WHERE keyspace_name='ks1'"),
+        assertRows(execute("SELECT table_name, min_compaction_threshold FROM system_schema.tables WHERE keyspace_name='ks1'"),
                    row("cf1", 7));
 
         // clean-up
@@ -195,8 +201,8 @@ public class AlterTest extends CQLTester
     // tests CASSANDRA-9565
     public void testDoubleWith() throws Throwable
     {
-        String[] stmts = new String[] { "ALTER KEYSPACE WITH WITH DURABLE_WRITES = true",
-                                        "ALTER KEYSPACE ks WITH WITH DURABLE_WRITES = true" };
+        String[] stmts = { "ALTER KEYSPACE WITH WITH DURABLE_WRITES = true",
+                           "ALTER KEYSPACE ks WITH WITH DURABLE_WRITES = true" };
 
         for (String stmt : stmts) {
             assertInvalidSyntaxMessage("no viable alternative at input 'WITH'", stmt);

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
index 055c9d9..19f85bf 100644
--- a/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
+++ b/test/unit/org/apache/cassandra/cql3/validation/operations/InsertUpdateIfConditionTest.java
@@ -798,19 +798,19 @@ public class InsertUpdateIfConditionTest extends CQLTester
         // create and confirm
         schemaChange("CREATE TABLE IF NOT EXISTS " + fullTableName + " (id text PRIMARY KEY, value1 blob) with comment = 'foo'");
 
-        assertRows(execute("select comment from system.schema_columnfamilies where keyspace_name = ? and columnfamily_name = ?", KEYSPACE, tableName),
+        assertRows(execute("select comment from system_schema.tables where keyspace_name = ? and table_name = ?", KEYSPACE, tableName),
                    row("foo"));
 
         // unsuccessful create since it's already there, confirm settings don't change
         schemaChange("CREATE TABLE IF NOT EXISTS " + fullTableName + " (id text PRIMARY KEY, value2 blob)with comment = 'bar'");
 
-        assertRows(execute("select comment from system.schema_columnfamilies where keyspace_name = ? and columnfamily_name = ?", KEYSPACE, tableName),
+        assertRows(execute("select comment from system_schema.tables where keyspace_name = ? and table_name = ?", KEYSPACE, tableName),
                    row("foo"));
 
         // drop and confirm
         schemaChange("DROP TABLE IF EXISTS " + fullTableName);
 
-        assertEmpty(execute("select * from system.schema_columnfamilies where keyspace_name = ? and columnfamily_name = ?", KEYSPACE, tableName));
+        assertEmpty(execute("select * from system_schema.tables where keyspace_name = ? and table_name = ?", KEYSPACE, tableName));
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/schema/DefsTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/schema/DefsTest.java b/test/unit/org/apache/cassandra/schema/DefsTest.java
index dcc4c51..cf49253 100644
--- a/test/unit/org/apache/cassandra/schema/DefsTest.java
+++ b/test/unit/org/apache/cassandra/schema/DefsTest.java
@@ -515,7 +515,7 @@ public class DefsTest
     public void testDropIndex() throws ConfigurationException
     {
         // persist keyspace definition in the system keyspace
-        LegacySchemaTables.makeCreateKeyspaceMutation(Schema.instance.getKSMetaData(KEYSPACE6), FBUtilities.timestampMicros()).applyUnsafe();
+        SchemaKeyspace.makeCreateKeyspaceMutation(Schema.instance.getKSMetaData(KEYSPACE6), FBUtilities.timestampMicros()).applyUnsafe();
         ColumnFamilyStore cfs = Keyspace.open(KEYSPACE6).getColumnFamilyStore(TABLE1i);
 
         // insert some data.  save the sstable descriptor so we can make sure it's marked for delete after the drop

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/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
new file mode 100644
index 0000000..b4149a0
--- /dev/null
+++ b/test/unit/org/apache/cassandra/schema/LegacySchemaMigratorTest.java
@@ -0,0 +1,549 @@
+/*
+ * 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.*;
+import java.util.stream.Collectors;
+
+import com.google.common.collect.ImmutableList;
+import org.junit.Test;
+
+import org.apache.cassandra.SchemaLoader;
+import org.apache.cassandra.cache.CachingOptions;
+import org.apache.cassandra.config.*;
+import org.apache.cassandra.cql3.ColumnIdentifier;
+import org.apache.cassandra.cql3.functions.*;
+import org.apache.cassandra.db.*;
+import org.apache.cassandra.db.compaction.LeveledCompactionStrategy;
+import org.apache.cassandra.db.marshal.*;
+
+import static java.lang.String.format;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+import static org.apache.cassandra.cql3.QueryProcessor.executeOnceInternal;
+import static org.apache.cassandra.utils.ByteBufferUtil.bytes;
+import static org.apache.cassandra.utils.FBUtilities.json;
+
+@SuppressWarnings("deprecation")
+public class LegacySchemaMigratorTest
+{
+    private static final long TIMESTAMP = 1435908994000000L;
+
+    private static final String KEYSPACE_PREFIX = "LegacySchemaMigratorTest";
+
+    /*
+     * 1. Write a variety of different keyspaces/tables/types/function in the legacy manner, using legacy schema tables
+     * 2. Run the migrator
+     * 3. Read all the keyspaces from the new schema tables
+     * 4. Make sure that we've read *exactly* the same set of keyspaces/tables/types/functions
+     * 5. Validate that the legacy schema tables are now empty
+     */
+    @Test
+    public void testMigrate()
+    {
+        List<KeyspaceMetadata> expected = keyspaceToMigrate();
+        expected.sort((k1, k2) -> k1.name.compareTo(k2.name));
+
+        // write the keyspaces into the legacy tables
+        expected.forEach(LegacySchemaMigratorTest::legacySerializeKeyspace);
+
+        // run the migration
+        LegacySchemaMigrator.migrate();
+
+        // read back all the metadata from the new schema tables
+        List<KeyspaceMetadata> actual = SchemaKeyspace.readSchemaFromSystemTables();
+        actual.sort((k1, k2) -> k1.name.compareTo(k2.name));
+
+        // make sure that we've read *exactly* the same set of keyspaces/tables/types/functions
+        assertEquals(expected, actual);
+
+        // need to load back CFMetaData of those tables (CFS instances will still be loaded)
+        loadLegacySchemaTables();
+
+        // verify that nothing's left in the old schema tables
+        for (CFMetaData table : LegacySchemaMigrator.LegacySchemaTables)
+        {
+            String query = format("SELECT * FROM %s.%s", SystemKeyspace.NAME, table.cfName);
+            //noinspection ConstantConditions
+            assertTrue(executeOnceInternal(query).isEmpty());
+        }
+    }
+
+    private static void loadLegacySchemaTables()
+    {
+        KeyspaceMetadata systemKeyspace = Schema.instance.getKSMetaData(SystemKeyspace.NAME);
+
+        Tables systemTables = systemKeyspace.tables;
+        for (CFMetaData table : LegacySchemaMigrator.LegacySchemaTables)
+            systemTables = systemTables.with(table);
+
+        LegacySchemaMigrator.LegacySchemaTables.forEach(Schema.instance::load);
+
+        Schema.instance.setKeyspaceMetadata(systemKeyspace.withSwapped(systemTables));
+    }
+
+    private static List<KeyspaceMetadata> keyspaceToMigrate()
+    {
+        List<KeyspaceMetadata> keyspaces = new ArrayList<>();
+
+        // A whole bucket of shorthand
+        String ks1 = KEYSPACE_PREFIX + "Keyspace1";
+        String ks2 = KEYSPACE_PREFIX + "Keyspace2";
+        String ks3 = KEYSPACE_PREFIX + "Keyspace3";
+        String ks4 = KEYSPACE_PREFIX + "Keyspace4";
+        String ks5 = KEYSPACE_PREFIX + "Keyspace5";
+        String ks6 = KEYSPACE_PREFIX + "Keyspace6";
+        String ks_rcs = KEYSPACE_PREFIX + "RowCacheSpace";
+        String ks_nocommit = KEYSPACE_PREFIX + "NoCommitlogSpace";
+        String ks_prsi = KEYSPACE_PREFIX + "PerRowSecondaryIndex";
+        String ks_cql = KEYSPACE_PREFIX + "cql_keyspace";
+
+        // Make it easy to test compaction
+        Map<String, String> compactionOptions = new HashMap<>();
+        compactionOptions.put("tombstone_compaction_interval", "1");
+        Map<String, String> leveledOptions = new HashMap<>();
+        leveledOptions.put("sstable_size_in_mb", "1");
+
+        keyspaces.add(KeyspaceMetadata.create(ks1,
+                                              KeyspaceParams.simple(1),
+                                              Tables.of(SchemaLoader.standardCFMD(ks1, "Standard1")
+                                                                    .compactionStrategyOptions(compactionOptions),
+                                                        SchemaLoader.standardCFMD(ks1, "StandardGCGS0").gcGraceSeconds(0),
+                                                        SchemaLoader.standardCFMD(ks1, "StandardLong1"),
+                                                        SchemaLoader.superCFMD(ks1, "Super1", LongType.instance),
+                                                        SchemaLoader.superCFMD(ks1, "Super2", UTF8Type.instance),
+                                                        SchemaLoader.superCFMD(ks1, "Super5", BytesType.instance),
+                                                        SchemaLoader.superCFMD(ks1, "Super6", LexicalUUIDType.instance, UTF8Type.instance),
+                                                        SchemaLoader.keysIndexCFMD(ks1, "Indexed1", true),
+                                                        SchemaLoader.keysIndexCFMD(ks1, "Indexed2", false),
+                                                        SchemaLoader.superCFMD(ks1, "SuperDirectGC", BytesType.instance)
+                                                                    .gcGraceSeconds(0),
+                                                        SchemaLoader.jdbcCFMD(ks1, "JdbcUtf8", UTF8Type.instance)
+                                                                    .addColumnDefinition(SchemaLoader.utf8Column(ks1, "JdbcUtf8")),
+                                                        SchemaLoader.jdbcCFMD(ks1, "JdbcLong", LongType.instance),
+                                                        SchemaLoader.jdbcCFMD(ks1, "JdbcBytes", BytesType.instance),
+                                                        SchemaLoader.jdbcCFMD(ks1, "JdbcAscii", AsciiType.instance),
+                                                        SchemaLoader.standardCFMD(ks1, "StandardLeveled")
+                                                                    .compactionStrategyClass(LeveledCompactionStrategy.class)
+                                                                    .compactionStrategyOptions(leveledOptions),
+                                                        SchemaLoader.standardCFMD(ks1, "legacyleveled")
+                                                                    .compactionStrategyClass(LeveledCompactionStrategy.class)
+                                                                    .compactionStrategyOptions(leveledOptions),
+                                                        SchemaLoader.standardCFMD(ks1, "StandardLowIndexInterval")
+                                                                    .minIndexInterval(8)
+                                                                    .maxIndexInterval(256)
+                                                                    .caching(CachingOptions.NONE))));
+
+        // Keyspace 2
+        keyspaces.add(KeyspaceMetadata.create(ks2,
+                                              KeyspaceParams.simple(1),
+                                              Tables.of(SchemaLoader.standardCFMD(ks2, "Standard1"),
+                                                        SchemaLoader.superCFMD(ks2, "Super3", BytesType.instance),
+                                                        SchemaLoader.superCFMD(ks2, "Super4", TimeUUIDType.instance),
+                                                        SchemaLoader.keysIndexCFMD(ks2, "Indexed1", true),
+                                                        SchemaLoader.compositeIndexCFMD(ks2, "Indexed2", true),
+                                                        SchemaLoader.compositeIndexCFMD(ks2, "Indexed3", true)
+                                                                    .gcGraceSeconds(0))));
+
+        // Keyspace 3
+        keyspaces.add(KeyspaceMetadata.create(ks3,
+                                              KeyspaceParams.simple(5),
+                                              Tables.of(SchemaLoader.standardCFMD(ks3, "Standard1"),
+                                                        SchemaLoader.keysIndexCFMD(ks3, "Indexed1", true))));
+
+        // Keyspace 4
+        keyspaces.add(KeyspaceMetadata.create(ks4,
+                                              KeyspaceParams.simple(3),
+                                              Tables.of(SchemaLoader.standardCFMD(ks4, "Standard1"),
+                                                        SchemaLoader.superCFMD(ks4, "Super3", BytesType.instance),
+                                                        SchemaLoader.superCFMD(ks4, "Super4", TimeUUIDType.instance),
+                                                        SchemaLoader.superCFMD(ks4, "Super5", TimeUUIDType.instance, BytesType.instance))));
+
+        // Keyspace 5
+        keyspaces.add(KeyspaceMetadata.create(ks5,
+                                              KeyspaceParams.simple(2),
+                                              Tables.of(SchemaLoader.standardCFMD(ks5, "Standard1"))));
+        // Keyspace 6
+        keyspaces.add(KeyspaceMetadata.create(ks6,
+                                              KeyspaceParams.simple(1),
+                                              Tables.of(SchemaLoader.keysIndexCFMD(ks6, "Indexed1", true))));
+
+        // RowCacheSpace
+        keyspaces.add(KeyspaceMetadata.create(ks_rcs,
+                                              KeyspaceParams.simple(1),
+                                              Tables.of(SchemaLoader.standardCFMD(ks_rcs, "CFWithoutCache")
+                                                                    .caching(CachingOptions.NONE),
+                                                        SchemaLoader.standardCFMD(ks_rcs, "CachedCF")
+                                                                    .caching(CachingOptions.ALL),
+                                                        SchemaLoader.standardCFMD(ks_rcs, "CachedIntCF")
+                                                                    .caching(new CachingOptions(new CachingOptions.KeyCache(CachingOptions.KeyCache.Type.ALL),
+                                                                                                new CachingOptions.RowCache(CachingOptions.RowCache.Type.HEAD, 100))))));
+
+
+        keyspaces.add(KeyspaceMetadata.create(ks_nocommit,
+                                              KeyspaceParams.simpleTransient(1),
+                                              Tables.of(SchemaLoader.standardCFMD(ks_nocommit, "Standard1"))));
+
+        // PerRowSecondaryIndexTest
+        keyspaces.add(KeyspaceMetadata.create(ks_prsi,
+                                              KeyspaceParams.simple(1),
+                                              Tables.of(SchemaLoader.perRowIndexedCFMD(ks_prsi, "Indexed1"))));
+
+        // CQLKeyspace
+        keyspaces.add(KeyspaceMetadata.create(ks_cql,
+                                              KeyspaceParams.simple(1),
+                                              Tables.of(CFMetaData.compile("CREATE TABLE table1 ("
+                                                                           + "k int PRIMARY KEY,"
+                                                                           + "v1 text,"
+                                                                           + "v2 int"
+                                                                           + ')', ks_cql),
+
+                                                        CFMetaData.compile("CREATE TABLE table2 ("
+                                                                           + "k text,"
+                                                                           + "c text,"
+                                                                           + "v text,"
+                                                                           + "PRIMARY KEY (k, c))", ks_cql),
+
+                                                        CFMetaData.compile("CREATE TABLE foo ("
+                                                                           + "bar text, "
+                                                                           + "baz text, "
+                                                                           + "qux text, "
+                                                                           + "PRIMARY KEY(bar, baz) ) "
+                                                                           + "WITH COMPACT STORAGE", ks_cql),
+
+                                                        CFMetaData.compile("CREATE TABLE foofoo ("
+                                                                           + "bar text, "
+                                                                           + "baz text, "
+                                                                           + "qux text, "
+                                                                           + "quz text, "
+                                                                           + "foo text, "
+                                                                           + "PRIMARY KEY((bar, baz), qux, quz) ) "
+                                                                           + "WITH COMPACT STORAGE", ks_cql))));
+
+        keyspaces.add(keyspaceWithTriggers());
+        keyspaces.add(keyspaceWithUDTs());
+        keyspaces.add(keyspaceWithUDFs());
+        keyspaces.add(keyspaceWithUDAs());
+
+        return keyspaces;
+    }
+
+    private static KeyspaceMetadata keyspaceWithTriggers()
+    {
+        String keyspace = KEYSPACE_PREFIX + "Triggers";
+
+        CFMetaData table = SchemaLoader.standardCFMD(keyspace, "WithTriggers");
+        for (int i = 0; i < 10; i++)
+            table.addTriggerDefinition(new TriggerDefinition("trigger" + i, "DummyTrigger" + i));
+
+        return KeyspaceMetadata.create(keyspace, KeyspaceParams.simple(1), Tables.of(table));
+    }
+
+    private static KeyspaceMetadata keyspaceWithUDTs()
+    {
+        String keyspace = KEYSPACE_PREFIX + "UDTs";
+
+        UserType udt1 = new UserType(keyspace,
+                                     bytes("udt1"),
+                                     new ArrayList<ByteBuffer>() {{ add(bytes("col1")); add(bytes("col2")); }},
+                                     new ArrayList<AbstractType<?>>() {{ add(UTF8Type.instance); add(Int32Type.instance); }});
+
+        UserType udt2 = new UserType(keyspace,
+                                     bytes("udt2"),
+                                     new ArrayList<ByteBuffer>() {{ add(bytes("col3")); add(bytes("col4")); }},
+                                     new ArrayList<AbstractType<?>>() {{ add(BytesType.instance); add(BooleanType.instance); }});
+
+        UserType udt3 = new UserType(keyspace,
+                                     bytes("udt3"),
+                                     new ArrayList<ByteBuffer>() {{ add(bytes("col5")); }},
+                                     new ArrayList<AbstractType<?>>() {{ add(AsciiType.instance); }});
+
+        return KeyspaceMetadata.create(keyspace,
+                                       KeyspaceParams.simple(1),
+                                       Tables.none(),
+                                       Types.of(udt1, udt2, udt3),
+                                       Functions.none());
+    }
+
+    private static KeyspaceMetadata keyspaceWithUDFs()
+    {
+        String keyspace = KEYSPACE_PREFIX + "UDFs";
+
+
+        UDFunction udf1 = UDFunction.create(new FunctionName(keyspace, "udf"),
+                                            ImmutableList.of(new ColumnIdentifier("col1", false), new ColumnIdentifier("col2", false)),
+                                            ImmutableList.of(BytesType.instance, Int32Type.instance),
+                                            LongType.instance,
+                                            false,
+                                            "java",
+                                            "return 42L;");
+
+        // an overload with the same name, not a typo
+        UDFunction udf2 = UDFunction.create(new FunctionName(keyspace, "udf"),
+                                            ImmutableList.of(new ColumnIdentifier("col3", false), new ColumnIdentifier("col4", false)),
+                                            ImmutableList.of(AsciiType.instance, LongType.instance),
+                                            Int32Type.instance,
+                                            true,
+                                            "java",
+                                            "return 42;");
+
+        UDFunction udf3 = UDFunction.create(new FunctionName(keyspace, "udf3"),
+                                            ImmutableList.of(new ColumnIdentifier("col4", false)),
+                                            ImmutableList.of(UTF8Type.instance),
+                                            BooleanType.instance,
+                                            false,
+                                            "java",
+                                            "return true;");
+
+        return KeyspaceMetadata.create(keyspace,
+                                       KeyspaceParams.simple(1),
+                                       Tables.none(),
+                                       Types.none(),
+                                       Functions.of(udf1, udf2, udf3));
+    }
+
+    // TODO: add representative UDAs set
+    private static KeyspaceMetadata keyspaceWithUDAs()
+    {
+        String keyspace = KEYSPACE_PREFIX + "UDAs";
+
+        return KeyspaceMetadata.create(keyspace,
+                                       KeyspaceParams.simple(1),
+                                       Tables.none(),
+                                       Types.none(),
+                                       Functions.of());
+    }
+
+    /*
+     * Serializing keyspaces
+     */
+
+    private static void legacySerializeKeyspace(KeyspaceMetadata keyspace)
+    {
+        makeLegacyCreateKeyspaceMutation(keyspace, TIMESTAMP).apply();
+    }
+
+    private static Mutation makeLegacyCreateKeyspaceMutation(KeyspaceMetadata keyspace, long timestamp)
+    {
+        // Note that because Keyspaces is a COMPACT TABLE, we're really only setting static columns internally and shouldn't set any clustering.
+        RowUpdateBuilder adder = new RowUpdateBuilder(SystemKeyspace.LegacyKeyspaces, timestamp, keyspace.name);
+
+        adder.add("durable_writes", keyspace.params.durableWrites)
+             .add("strategy_class", keyspace.params.replication.klass.getName())
+             .add("strategy_options", json(keyspace.params.replication.options));
+
+        Mutation mutation = adder.build();
+
+        keyspace.tables.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));
+
+        return mutation;
+    }
+
+    /*
+     * Serializing tables
+     */
+
+    private static void addTableToSchemaMutation(CFMetaData table, long timestamp, boolean withColumnsAndTriggers, Mutation mutation)
+    {
+        // For property that can be null (and can be changed), we insert tombstones, to make sure
+        // we don't keep a property the user has removed
+        RowUpdateBuilder adder = new RowUpdateBuilder(SystemKeyspace.LegacyColumnfamilies, timestamp, mutation)
+                                 .clustering(table.cfName);
+
+        adder.add("cf_id", table.cfId)
+             .add("type", table.isSuper() ? "Super" : "Standard");
+
+        if (table.isSuper())
+        {
+            adder.add("comparator", table.comparator.subtype(0).toString())
+                 .add("subcomparator", ((MapType)table.compactValueColumn().type).getKeysType().toString());
+        }
+        else
+        {
+            adder.add("comparator", LegacyLayout.makeLegacyComparator(table).toString());
+        }
+
+        adder.add("bloom_filter_fp_chance", table.getBloomFilterFpChance())
+             .add("caching", table.getCaching().toString())
+             .add("comment", table.getComment())
+             .add("compaction_strategy_class", table.compactionStrategyClass.getName())
+             .add("compaction_strategy_options", json(table.compactionStrategyOptions))
+             .add("compression_parameters", json(table.compressionParameters.asThriftOptions()))
+             .add("default_time_to_live", table.getDefaultTimeToLive())
+             .add("gc_grace_seconds", table.getGcGraceSeconds())
+             .add("key_validator", table.getKeyValidator().toString())
+             .add("local_read_repair_chance", table.getDcLocalReadRepairChance())
+             .add("max_compaction_threshold", table.getMaxCompactionThreshold())
+             .add("max_index_interval", table.getMaxIndexInterval())
+             .add("memtable_flush_period_in_ms", table.getMemtableFlushPeriod())
+             .add("min_compaction_threshold", table.getMinCompactionThreshold())
+             .add("min_index_interval", table.getMinIndexInterval())
+             .add("read_repair_chance", table.getReadRepairChance())
+             .add("speculative_retry", table.getSpeculativeRetry().toString());
+
+        for (Map.Entry<ColumnIdentifier, CFMetaData.DroppedColumn> entry : table.getDroppedColumns().entrySet())
+        {
+            String name = entry.getKey().toString();
+            CFMetaData.DroppedColumn column = entry.getValue();
+            adder.addMapEntry("dropped_columns", name, column.droppedTime);
+            if (column.type != null)
+                adder.addMapEntry("dropped_columns_types", name, column.type.toString());
+        }
+
+        adder.add("is_dense", table.isDense());
+
+        adder.add("default_validator", table.makeLegacyDefaultValidator().toString());
+
+        if (withColumnsAndTriggers)
+        {
+            for (ColumnDefinition column : table.allColumns())
+                addColumnToSchemaMutation(table, column, timestamp, mutation);
+
+            for (TriggerDefinition trigger : table.getTriggers().values())
+                addTriggerToSchemaMutation(table, trigger, timestamp, mutation);
+        }
+
+        adder.build();
+    }
+
+    private static void addColumnToSchemaMutation(CFMetaData table, ColumnDefinition column, long timestamp, Mutation mutation)
+    {
+        RowUpdateBuilder adder = new RowUpdateBuilder(SystemKeyspace.LegacyColumns, timestamp, mutation)
+                                 .clustering(table.cfName, column.name.toString());
+
+        adder.add("validator", column.type.toString())
+             .add("type", serializeKind(column.kind, table.isDense()))
+             .add("component_index", column.isOnAllComponents() ? null : column.position())
+             .add("index_name", column.getIndexName())
+             .add("index_type", column.getIndexType() == null ? null : column.getIndexType().toString())
+             .add("index_options", json(column.getIndexOptions()))
+             .build();
+    }
+
+    private static String serializeKind(ColumnDefinition.Kind kind, boolean isDense)
+    {
+        // For backward compatibility, we special case CLUSTERING_COLUMN and the case where the table is dense.
+        if (kind == ColumnDefinition.Kind.CLUSTERING_COLUMN)
+            return "clustering_key";
+
+        if (kind == ColumnDefinition.Kind.REGULAR && isDense)
+            return "compact_value";
+
+        return kind.toString().toLowerCase();
+    }
+
+    private static void addTriggerToSchemaMutation(CFMetaData table, TriggerDefinition trigger, long timestamp, Mutation mutation)
+    {
+        new RowUpdateBuilder(SystemKeyspace.LegacyTriggers, timestamp, mutation)
+            .clustering(table.cfName, trigger.name)
+            .addMapEntry("trigger_options", "class", trigger.classOption)
+            .build();
+    }
+
+    /*
+     * Serializing types
+     */
+
+    private static void addTypeToSchemaMutation(UserType type, long timestamp, Mutation mutation)
+    {
+        RowUpdateBuilder adder = new RowUpdateBuilder(SystemKeyspace.LegacyUsertypes, timestamp, mutation)
+                                 .clustering(type.getNameAsString());
+
+        adder.resetCollection("field_names")
+             .resetCollection("field_types");
+
+        for (int i = 0; i < type.size(); i++)
+        {
+            adder.addListEntry("field_names", type.fieldName(i))
+                 .addListEntry("field_types", type.fieldType(i).toString());
+        }
+
+        adder.build();
+    }
+
+    /*
+     * Serializing functions
+     */
+
+    private static void addFunctionToSchemaMutation(UDFunction function, long timestamp, Mutation mutation)
+    {
+        RowUpdateBuilder adder = new RowUpdateBuilder(SystemKeyspace.LegacyFunctions, timestamp, mutation)
+                                 .clustering(function.name().name, functionSignatureWithTypes(function));
+
+        adder.add("body", function.body())
+             .add("language", function.language())
+             .add("return_type", function.returnType().toString())
+             .add("called_on_null_input", function.isCalledOnNullInput());
+
+        adder.resetCollection("argument_names")
+             .resetCollection("argument_types");
+
+        for (int i = 0; i < function.argNames().size(); i++)
+        {
+            adder.addListEntry("argument_names", function.argNames().get(i).bytes)
+                 .addListEntry("argument_types", function.argTypes().get(i).toString());
+        }
+
+        adder.build();
+    }
+
+    /*
+     * Serializing aggregates
+     */
+
+    private static void addAggregateToSchemaMutation(UDAggregate aggregate, long timestamp, Mutation mutation)
+    {
+        RowUpdateBuilder adder = new RowUpdateBuilder(SystemKeyspace.LegacyAggregates, timestamp, mutation)
+                                 .clustering(aggregate.name().name, functionSignatureWithTypes(aggregate));
+
+        adder.resetCollection("argument_types");
+
+        adder.add("return_type", aggregate.returnType().toString())
+             .add("state_func", aggregate.stateFunction().name().toString());
+
+        if (aggregate.stateType() != null)
+            adder.add("state_type", aggregate.stateType().toString());
+        if (aggregate.finalFunction() != null)
+            adder.add("final_func", aggregate.finalFunction().name().toString());
+        if (aggregate.initialCondition() != null)
+            adder.add("initcond", aggregate.initialCondition());
+
+        for (AbstractType<?> argType : aggregate.argTypes())
+            adder.addListEntry("argument_types", argType.toString());
+
+        adder.build();
+    }
+
+    // We allow method overloads, so a function is not uniquely identified by its name only, but
+    // also by its argument types. To distinguish overloads of given function name in the schema
+    // we use a "signature" which is just a list of it's CQL argument types.
+    public static ByteBuffer functionSignatureWithTypes(AbstractFunction fun)
+    {
+        List<String> arguments =
+            fun.argTypes()
+               .stream()
+               .map(argType -> argType.asCQL3Type().toString())
+               .collect(Collectors.toList());
+
+        return ListType.getInstance(UTF8Type.instance, false).decompose(arguments);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java b/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
new file mode 100644
index 0000000..715799b
--- /dev/null
+++ b/test/unit/org/apache/cassandra/schema/SchemaKeyspaceTest.java
@@ -0,0 +1,153 @@
+/*
+ * 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.ArrayList;
+import java.util.List;
+import java.util.HashMap;
+import java.util.HashSet;
+
+import org.apache.cassandra.SchemaLoader;
+import org.apache.cassandra.config.CFMetaData;
+import org.apache.cassandra.config.Schema;
+import org.apache.cassandra.db.*;
+import org.apache.cassandra.db.rows.UnfilteredRowIterators;
+import org.apache.cassandra.db.partitions.PartitionUpdate;
+import org.apache.cassandra.db.marshal.AsciiType;
+import org.apache.cassandra.db.marshal.UTF8Type;
+import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.io.compress.*;
+import org.apache.cassandra.schema.KeyspaceMetadata;
+import org.apache.cassandra.schema.KeyspaceParams;
+import org.apache.cassandra.schema.SchemaKeyspace;
+import org.apache.cassandra.thrift.CfDef;
+import org.apache.cassandra.thrift.ColumnDef;
+import org.apache.cassandra.thrift.IndexType;
+import org.apache.cassandra.thrift.ThriftConversion;
+import org.apache.cassandra.utils.ByteBufferUtil;
+import org.apache.cassandra.utils.FBUtilities;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class SchemaKeyspaceTest
+{
+    private static final String KEYSPACE1 = "CFMetaDataTest1";
+    private static final String CF_STANDARD1 = "Standard1";
+
+    private static final List<ColumnDef> columnDefs = new ArrayList<>();
+
+    static
+    {
+        columnDefs.add(new ColumnDef(ByteBufferUtil.bytes("col1"), AsciiType.class.getCanonicalName())
+                                    .setIndex_name("col1Index")
+                                    .setIndex_type(IndexType.KEYS));
+
+        columnDefs.add(new ColumnDef(ByteBufferUtil.bytes("col2"), UTF8Type.class.getCanonicalName())
+                                    .setIndex_name("col2Index")
+                                    .setIndex_type(IndexType.KEYS));
+    }
+
+    @BeforeClass
+    public static void defineSchema() throws ConfigurationException
+    {
+        SchemaLoader.prepareServer();
+        SchemaLoader.createKeyspace(KEYSPACE1,
+                                    KeyspaceParams.simple(1),
+                                    SchemaLoader.standardCFMD(KEYSPACE1, CF_STANDARD1));
+    }
+
+    @Test
+    public void testThriftConversion() throws Exception
+    {
+        CfDef cfDef = new CfDef().setDefault_validation_class(AsciiType.class.getCanonicalName())
+                                 .setComment("Test comment")
+                                 .setColumn_metadata(columnDefs)
+                                 .setKeyspace(KEYSPACE1)
+                                 .setName(CF_STANDARD1);
+
+        // convert Thrift to CFMetaData
+        CFMetaData cfMetaData = ThriftConversion.fromThrift(cfDef);
+
+        CfDef thriftCfDef = new CfDef();
+        thriftCfDef.keyspace = KEYSPACE1;
+        thriftCfDef.name = CF_STANDARD1;
+        thriftCfDef.default_validation_class = cfDef.default_validation_class;
+        thriftCfDef.comment = cfDef.comment;
+        thriftCfDef.column_metadata = new ArrayList<>();
+        for (ColumnDef columnDef : columnDefs)
+        {
+            ColumnDef c = new ColumnDef();
+            c.name = ByteBufferUtil.clone(columnDef.name);
+            c.validation_class = columnDef.getValidation_class();
+            c.index_name = columnDef.getIndex_name();
+            c.index_type = IndexType.KEYS;
+            thriftCfDef.column_metadata.add(c);
+        }
+
+        CfDef converted = ThriftConversion.toThrift(cfMetaData);
+
+        assertEquals(thriftCfDef.keyspace, converted.keyspace);
+        assertEquals(thriftCfDef.name, converted.name);
+        assertEquals(thriftCfDef.default_validation_class, converted.default_validation_class);
+        assertEquals(thriftCfDef.comment, converted.comment);
+        assertEquals(new HashSet<>(thriftCfDef.column_metadata), new HashSet<>(converted.column_metadata));
+    }
+
+    @Test
+    public void testConversionsInverses() throws Exception
+    {
+        for (String keyspaceName : Schema.instance.getNonSystemKeyspaces())
+        {
+            for (ColumnFamilyStore cfs : Keyspace.open(keyspaceName).getColumnFamilyStores())
+            {
+                CFMetaData cfm = cfs.metadata;
+                if (!cfm.isThriftCompatible())
+                    continue;
+
+                checkInverses(cfm);
+
+                // Testing with compression to catch #3558
+                CFMetaData withCompression = cfm.copy();
+                withCompression.compressionParameters(new CompressionParameters(SnappyCompressor.instance, 32768, new HashMap<>()));
+                checkInverses(withCompression);
+            }
+        }
+    }
+
+    private static void checkInverses(CFMetaData cfm) throws Exception
+    {
+        KeyspaceMetadata keyspace = Schema.instance.getKSMetaData(cfm.ksName);
+
+        // Test thrift conversion
+        CFMetaData before = cfm;
+        CFMetaData after = ThriftConversion.fromThriftForUpdate(ThriftConversion.toThrift(before), before);
+        assert before.equals(after) : String.format("%n%s%n!=%n%s", before, after);
+
+        // Test schema conversion
+        Mutation rm = SchemaKeyspace.makeCreateTableMutation(keyspace, cfm, FBUtilities.timestampMicros());
+        PartitionUpdate serializedCf = rm.getPartitionUpdate(Schema.instance.getId(SystemKeyspace.NAME, SchemaKeyspace.TABLES));
+        PartitionUpdate serializedCD = rm.getPartitionUpdate(Schema.instance.getId(SystemKeyspace.NAME, SchemaKeyspace.COLUMNS));
+        CFMetaData newCfm = SchemaKeyspace.createTableFromTablePartitionAndColumnsPartition(UnfilteredRowIterators.filter(serializedCf.unfilteredIterator(), FBUtilities.nowInSeconds()),
+                                                                                            UnfilteredRowIterators.filter(serializedCD.unfilteredIterator(), FBUtilities.nowInSeconds()));
+        assert cfm.equals(newCfm) : String.format("%n%s%n!=%n%s", cfm, newCfm);
+    }
+}

http://git-wip-us.apache.org/repos/asf/cassandra/blob/7d6c876e/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java
----------------------------------------------------------------------
diff --git a/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java b/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java
index 0819097..e716eda 100644
--- a/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java
+++ b/test/unit/org/apache/cassandra/service/StorageServiceServerTest.java
@@ -38,7 +38,6 @@ import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.schema.KeyspaceMetadata;
 import org.apache.cassandra.config.Schema;
 import org.apache.cassandra.db.Keyspace;
-import org.apache.cassandra.db.SystemKeyspace;
 import org.apache.cassandra.db.WindowsFailedSnapshotTracker;
 import org.apache.cassandra.dht.Murmur3Partitioner;
 import org.apache.cassandra.dht.Murmur3Partitioner.LongToken;
@@ -50,7 +49,7 @@ import org.apache.cassandra.locator.IEndpointSnitch;
 import org.apache.cassandra.locator.PropertyFileSnitch;
 import org.apache.cassandra.locator.TokenMetadata;
 import org.apache.cassandra.schema.KeyspaceParams;
-import org.apache.cassandra.schema.LegacySchemaTables;
+import org.apache.cassandra.schema.SchemaKeyspace;
 import org.apache.cassandra.utils.FBUtilities;
 
 import static org.junit.Assert.assertEquals;
@@ -173,7 +172,7 @@ public class StorageServiceServerTest
     public void testColumnFamilySnapshot() throws IOException
     {
         // no need to insert extra data, even an "empty" database will have a little information in the system keyspace
-        StorageService.instance.takeColumnFamilySnapshot(SystemKeyspace.NAME, LegacySchemaTables.KEYSPACES, "cf_snapshot");
+        StorageService.instance.takeColumnFamilySnapshot(SchemaKeyspace.NAME, SchemaKeyspace.KEYSPACES, "cf_snapshot");
     }
 
     @Test


Mime
View raw message