From 5f8991c73a6f43fbe9c7e0d8906e751c21d54412 Mon Sep 17 00:00:00 2001 From: Jonathan Ellis Date: Sat, 7 May 2011 06:52:02 +0000 Subject: [PATCH] recognize attempt todrop just the index while leaving the column definition patch by jbellis; reviewed by brandonwilliams for CASSANDRA-2619 git-svn-id: https://svn.apache.org/repos/asf/cassandra/branches/cassandra-0.7@1100464 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES.txt | 2 + .../apache/cassandra/config/CFMetaData.java | 14 +- .../cassandra/db/ColumnFamilyStore.java | 3 +- test/conf/cassandra.yaml | 13 + .../org/apache/cassandra/db/DefsTest.java | 797 ------------------ 5 files changed, 24 insertions(+), 805 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 9926bd64c9..fc78fcec34 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -12,6 +12,8 @@ rebuffering in BRAF (CASSANDRA-2581) * include indexes in snapshots (CASSANDRA-2596) * improve ignoring of obsolete mutations in index maintenance (CASSANDRA-2401) + * recognize attempt to drop just the index while leaving the column + definition alone (CASSANDRA-2619) 0.7.5 diff --git a/src/java/org/apache/cassandra/config/CFMetaData.java b/src/java/org/apache/cassandra/config/CFMetaData.java index 5ea05c5e21..4e6158dde4 100644 --- a/src/java/org/apache/cassandra/config/CFMetaData.java +++ b/src/java/org/apache/cassandra/config/CFMetaData.java @@ -159,7 +159,7 @@ public final class CFMetaData private double memtableOperationsInMillions; // default based on throughput // NOTE: if you find yourself adding members to this class, make sure you keep the convert methods in lockstep. - private final Map column_metadata; + final Map column_metadata; private CFMetaData(String tableName, String cfName, @@ -664,19 +664,19 @@ public final class CFMetaData memtableThroughputInMb = cf_def.memtable_throughput_in_mb; memtableOperationsInMillions = cf_def.memtable_operations_in_millions; - // adjust secondary indexes. figure out who is coming and going. + // adjust column definitions. figure out who is coming and going. Set toRemove = new HashSet(); - Set newIndexNames = new HashSet(); + Set newColumns = new HashSet(); Set toAdd = new HashSet(); for (org.apache.cassandra.avro.ColumnDef def : cf_def.column_metadata) { - newIndexNames.add(def.name); + newColumns.add(def.name); if (!column_metadata.containsKey(def.name)) toAdd.add(def); } - for (ByteBuffer indexName : column_metadata.keySet()) - if (!newIndexNames.contains(indexName)) - toRemove.add(indexName); + for (ByteBuffer name : column_metadata.keySet()) + if (!newColumns.contains(name)) + toRemove.add(name); // remove the ones leaving. for (ByteBuffer indexName : toRemove) diff --git a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java index b20afdfb66..9d60fe0ab1 100644 --- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java +++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java @@ -177,7 +177,8 @@ public class ColumnFamilyStore implements ColumnFamilyStoreMBean // future: if/when we have modifiable settings for secondary indexes, they'll need to be handled here. for (ByteBuffer indexedColumn : indexedColumns.keySet()) { - if (!metadata.getColumn_metadata().containsKey(indexedColumn)) + ColumnDefinition def = metadata.getColumn_metadata().get(indexedColumn); + if (def == null || def.getIndexType() == null) removeIndex(indexedColumn); } diff --git a/test/conf/cassandra.yaml b/test/conf/cassandra.yaml index d5bb13d56e..4a13cce648 100644 --- a/test/conf/cassandra.yaml +++ b/test/conf/cassandra.yaml @@ -207,3 +207,16 @@ keyspaces: rows_cached: 100 - name: CFWithoutCache rows_cached: 0 + + - name: Keyspace6 + replica_placement_strategy: org.apache.cassandra.locator.SimpleStrategy + replication_factor: 1 + column_families: + - name: Indexed1 + column_metadata: + - name: birthdate + validator_class: LongType + index_type: KEYS + rows_cached: 0 + keys_cached: 0 + diff --git a/test/unit/org/apache/cassandra/db/DefsTest.java b/test/unit/org/apache/cassandra/db/DefsTest.java index db6752d8ad..e69de29bb2 100644 --- a/test/unit/org/apache/cassandra/db/DefsTest.java +++ b/test/unit/org/apache/cassandra/db/DefsTest.java @@ -1,797 +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.db; - -import static org.junit.Assert.assertEquals; - -import java.io.File; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.UUID; -import java.util.concurrent.ExecutionException; - -import org.apache.avro.util.Utf8; -import org.apache.cassandra.CleanupHelper; -import org.apache.cassandra.Util; -import org.apache.cassandra.config.CFMetaData; -import org.apache.cassandra.config.ColumnDefinition; -import org.apache.cassandra.config.ConfigurationException; -import org.apache.cassandra.config.DatabaseDescriptor; -import org.apache.cassandra.config.KSMetaData; -import org.apache.cassandra.db.filter.QueryFilter; -import org.apache.cassandra.db.filter.QueryPath; -import org.apache.cassandra.db.marshal.BytesType; -import org.apache.cassandra.db.marshal.UTF8Type; -import org.apache.cassandra.db.migration.AddColumnFamily; -import org.apache.cassandra.db.migration.AddKeyspace; -import org.apache.cassandra.db.migration.DropColumnFamily; -import org.apache.cassandra.db.migration.DropKeyspace; -import org.apache.cassandra.db.migration.Migration; -import org.apache.cassandra.db.migration.RenameColumnFamily; -import org.apache.cassandra.db.migration.RenameKeyspace; -import org.apache.cassandra.db.migration.UpdateColumnFamily; -import org.apache.cassandra.db.migration.UpdateKeyspace; -import org.apache.cassandra.io.SerDeUtils; -import org.apache.cassandra.locator.OldNetworkTopologyStrategy; -import org.apache.cassandra.locator.SimpleStrategy; -import org.apache.cassandra.thrift.IndexType; -import org.apache.cassandra.utils.FBUtilities; -import org.apache.cassandra.utils.UUIDGen; -import org.junit.Test; -import org.apache.cassandra.utils.ByteBufferUtil; - - -public class DefsTest extends CleanupHelper -{ - @Test - public void testZeroInjection() throws IOException - { - org.apache.cassandra.avro.CfDef cd = new org.apache.cassandra.avro.CfDef(); - // populate only fields that must be non-null. - cd.keyspace = new Utf8("Lest Ks"); - cd.name = new Utf8("Mest Cf"); - - org.apache.cassandra.avro.CfDef cd2 = SerDeUtils.deserializeWithSchema(SerDeUtils.serializeWithSchema(cd), new org.apache.cassandra.avro.CfDef()); - assert cd.equals(cd2); - // make sure some of the fields didn't get unexpected zeros put in during [de]serialize operations. - assert cd.min_compaction_threshold == null; - assert cd2.min_compaction_threshold == null; - assert cd.row_cache_save_period_in_seconds == null; - assert cd2.row_cache_save_period_in_seconds == null; - - } - - @Test - public void ensureStaticCFMIdsAreLessThan1000() - { - assert CFMetaData.StatusCf.cfId == 0; - assert CFMetaData.HintsCf.cfId == 1; - assert CFMetaData.MigrationsCf.cfId == 2; - assert CFMetaData.SchemaCf.cfId == 3; - } - - @Test - public void testCFMetaDataApply() throws ConfigurationException - { - Map indexes = new HashMap(); - for (int i = 0; i < 5; i++) - { - ByteBuffer name = ByteBuffer.wrap(new byte[] { (byte)i }); - indexes.put(name, new ColumnDefinition(name, null, IndexType.KEYS, Integer.toString(i))); - } - CFMetaData cfm = new CFMetaData("Keyspace1", - "TestApplyCFM_CF", - ColumnFamilyType.Standard, - BytesType.instance, - null, - "No comment", - 1.0, - 1.0, - 0.5, - 100000, - null, - 500, - 500, - 500, - 500, - 500, - 500, - 500.0, - indexes); - - // we'll be adding this one later. make sure it's not already there. - assert cfm.getColumn_metadata().get(ByteBuffer.wrap(new byte[] { 5 })) == null; - org.apache.cassandra.avro.CfDef cfDef = CFMetaData.convertToAvro(cfm); - - // add one. - org.apache.cassandra.avro.ColumnDef addIndexDef = new org.apache.cassandra.avro.ColumnDef(); - addIndexDef.index_name = "5"; - addIndexDef.index_type = org.apache.cassandra.avro.IndexType.KEYS; - addIndexDef.name = ByteBuffer.wrap(new byte[] { 5 }); - addIndexDef.validation_class = BytesType.class.getName(); - cfDef.column_metadata.add(addIndexDef); - - // remove one. - org.apache.cassandra.avro.ColumnDef removeIndexDef = new org.apache.cassandra.avro.ColumnDef(); - removeIndexDef.index_name = "0"; - removeIndexDef.index_type = org.apache.cassandra.avro.IndexType.KEYS; - removeIndexDef.name = ByteBuffer.wrap(new byte[] { 0 }); - removeIndexDef.validation_class = BytesType.class.getName(); - assert cfDef.column_metadata.remove(removeIndexDef); - - cfm.apply(cfDef); - - for (int i = 1; i < indexes.size(); i++) - assert cfm.getColumn_metadata().get(ByteBuffer.wrap(new byte[] { 1 })) != null; - assert cfm.getColumn_metadata().get(ByteBuffer.wrap(new byte[] { 0 })) == null; - assert cfm.getColumn_metadata().get(ByteBuffer.wrap(new byte[] { 5 })) != null; - } - - @Test - public void testInvalidNames() throws IOException - { - String[] valid = {"1", "a", "_1", "b_", "__", "1_a"}; - for (String s : valid) - assert Migration.isLegalName(s); - - String[] invalid = {"b@t", "dash-y", "", " ", "dot.s", ".hidden"}; - for (String s : invalid) - assert !Migration.isLegalName(s); - } - - @Test - public void saveAndRestore() throws IOException - { - // verify dump and reload. - UUID first = UUIDGen.makeType1UUIDFromHost(FBUtilities.getLocalAddress()); - DefsTable.dumpToStorage(first); - List defs = new ArrayList(DefsTable.loadFromStorage(first)); - - assert defs.size() > 0; - assert defs.size() == DatabaseDescriptor.getNonSystemTables().size(); - for (KSMetaData loaded : defs) - { - KSMetaData defined = DatabaseDescriptor.getTableDefinition(loaded.name); - assert defined.equals(loaded); - } - } - - @Test - public void addNewCfToBogusTable() throws InterruptedException - { - CFMetaData newCf = addTestCF("MadeUpKeyspace", "NewCF", "new cf"); - try - { - new AddColumnFamily(newCf).apply(); - throw new AssertionError("You shouldn't be able to do anything to a keyspace that doesn't exist."); - } - catch (ConfigurationException expected) - { - } - catch (IOException unexpected) - { - throw new AssertionError("Unexpected exception."); - } - } - - @Test - public void testMigrations() throws IOException, ConfigurationException - { - // do a save. make sure it doesn't mess with the defs version. - UUID prior = DatabaseDescriptor.getDefsVersion(); - UUID ver0 = UUIDGen.makeType1UUIDFromHost(FBUtilities.getLocalAddress()); - DefsTable.dumpToStorage(ver0); - assert DatabaseDescriptor.getDefsVersion().equals(prior); - - // add a cf. - CFMetaData newCf1 = addTestCF("Keyspace1", "MigrationCf_1", "Migration CF"); - - Migration m1 = new AddColumnFamily(newCf1); - m1.apply(); - UUID ver1 = m1.getVersion(); - assert DatabaseDescriptor.getDefsVersion().equals(ver1); - - // rename it. - Migration m2 = new RenameColumnFamily("Keyspace1", "MigrationCf_1", "MigrationCf_2"); - m2.apply(); - UUID ver2 = m2.getVersion(); - assert DatabaseDescriptor.getDefsVersion().equals(ver2); - - // drop it. - Migration m3 = new DropColumnFamily("Keyspace1", "MigrationCf_2"); - m3.apply(); - UUID ver3 = m3.getVersion(); - assert DatabaseDescriptor.getDefsVersion().equals(ver3); - - // now lets load the older migrations to see if that code works. - Collection serializedMigrations = Migration.getLocalMigrations(ver1, ver3); - assert serializedMigrations.size() == 3; - - // test deserialization of the migrations. - Migration[] reconstituded = new Migration[3]; - int i = 0; - for (IColumn col : serializedMigrations) - { - UUID version = UUIDGen.getUUID(col.name()); - reconstituded[i] = Migration.deserialize(col.value()); - assert version.equals(reconstituded[i].getVersion()); - i++; - } - - assert m1.getClass().equals(reconstituded[0].getClass()); - assert m2.getClass().equals(reconstituded[1].getClass()); - assert m3.getClass().equals(reconstituded[2].getClass()); - - // verify that the row mutations are the same. rather than exposing the private fields, serialize and verify. - assert m1.serialize().equals(reconstituded[0].serialize()); - assert m2.serialize().equals(reconstituded[1].serialize()); - assert m3.serialize().equals(reconstituded[2].serialize()); - } - - @Test - public void addNewCF() throws ConfigurationException, IOException, ExecutionException, InterruptedException - { - final String ks = "Keyspace1"; - final String cf = "BrandNewCf"; - KSMetaData original = DatabaseDescriptor.getTableDefinition(ks); - - CFMetaData newCf = addTestCF(original.name, cf, "A New Column Family"); - - assert !DatabaseDescriptor.getTableDefinition(ks).cfMetaData().containsKey(newCf.cfName); - new AddColumnFamily(newCf).apply(); - - assert DatabaseDescriptor.getTableDefinition(ks).cfMetaData().containsKey(newCf.cfName); - assert DatabaseDescriptor.getTableDefinition(ks).cfMetaData().get(newCf.cfName).equals(newCf); - - // now read and write to it. - DecoratedKey dk = Util.dk("key0"); - RowMutation rm = new RowMutation(ks, dk.key); - rm.add(new QueryPath(cf, null, ByteBufferUtil.bytes("col0")), ByteBufferUtil.bytes("value0"), 1L); - rm.apply(); - ColumnFamilyStore store = Table.open(ks).getColumnFamilyStore(cf); - assert store != null; - store.forceBlockingFlush(); - - ColumnFamily cfam = store.getColumnFamily(QueryFilter.getNamesFilter(dk, new QueryPath(cf), ByteBufferUtil.bytes("col0"))); - assert cfam.getColumn(ByteBufferUtil.bytes("col0")) != null; - IColumn col = cfam.getColumn(ByteBufferUtil.bytes("col0")); - assert ByteBufferUtil.bytes("value0").equals(col.value()); - } - - @Test - public void dropCf() throws ConfigurationException, IOException, ExecutionException, InterruptedException - { - DecoratedKey dk = Util.dk("dropCf"); - // sanity - final KSMetaData ks = DatabaseDescriptor.getTableDefinition("Keyspace1"); - assert ks != null; - final CFMetaData cfm = ks.cfMetaData().get("Standard1"); - assert cfm != null; - - // write some data, force a flush, then verify that files exist on disk. - RowMutation rm = new RowMutation(ks.name, dk.key); - for (int i = 0; i < 100; i++) - rm.add(new QueryPath(cfm.cfName, null, ByteBufferUtil.bytes(("col" + i))), ByteBufferUtil.bytes("anyvalue"), 1L); - rm.apply(); - ColumnFamilyStore store = Table.open(cfm.tableName).getColumnFamilyStore(cfm.cfName); - assert store != null; - store.forceBlockingFlush(); - assert DefsTable.getFiles(cfm.tableName, cfm.cfName).size() > 0; - - new DropColumnFamily(ks.name, cfm.cfName).apply(); - - assert !DatabaseDescriptor.getTableDefinition(ks.name).cfMetaData().containsKey(cfm.cfName); - - // any write should fail. - rm = new RowMutation(ks.name, dk.key); - boolean success = true; - try - { - rm.add(new QueryPath("Standard1", null, ByteBufferUtil.bytes("col0")), ByteBufferUtil.bytes("value0"), 1L); - rm.apply(); - } - catch (Throwable th) - { - success = false; - } - assert !success : "This mutation should have failed since the CF no longer exists."; - - // verify that the files are gone. - for (File file : DefsTable.getFiles(cfm.tableName, cfm.cfName)) - { - if (file.getPath().endsWith("Data.db") && !new File(file.getPath().replace("Data.db", "Compacted")).exists()) - throw new AssertionError("undeleted file " + file); - } - } - - @Test - public void renameCf() throws ConfigurationException, IOException, ExecutionException, InterruptedException - { - DecoratedKey dk = Util.dk("key0"); - final KSMetaData ks = DatabaseDescriptor.getTableDefinition("Keyspace2"); - assert ks != null; - final CFMetaData oldCfm = ks.cfMetaData().get("Standard1"); - assert oldCfm != null; - - // write some data, force a flush, then verify that files exist on disk. - RowMutation rm = new RowMutation(ks.name, dk.key); - for (int i = 0; i < 100; i++) - rm.add(new QueryPath(oldCfm.cfName, null, ByteBufferUtil.bytes(("col" + i))), ByteBufferUtil.bytes("anyvalue"), 1L); - rm.apply(); - ColumnFamilyStore store = Table.open(oldCfm.tableName).getColumnFamilyStore(oldCfm.cfName); - assert store != null; - store.forceBlockingFlush(); - int fileCount = DefsTable.getFiles(oldCfm.tableName, oldCfm.cfName).size(); - assert fileCount > 0; - - final String cfName = "St4ndard1Replacement"; - new RenameColumnFamily(oldCfm.tableName, oldCfm.cfName, cfName).apply(); - - assert !DatabaseDescriptor.getTableDefinition(ks.name).cfMetaData().containsKey(oldCfm.cfName); - assert DatabaseDescriptor.getTableDefinition(ks.name).cfMetaData().containsKey(cfName); - - // verify that new files are there. - assert DefsTable.getFiles(oldCfm.tableName, cfName).size() == fileCount; - - // do some reads. - store = Table.open(oldCfm.tableName).getColumnFamilyStore(cfName); - assert store != null; - ColumnFamily cfam = store.getColumnFamily(QueryFilter.getSliceFilter(dk, new QueryPath(cfName), ByteBufferUtil.EMPTY_BYTE_BUFFER, ByteBufferUtil.EMPTY_BYTE_BUFFER, false, 1000)); - assert cfam.getSortedColumns().size() == 100; // should be good enough? - - // do some writes - rm = new RowMutation(ks.name, dk.key); - rm.add(new QueryPath(cfName, null, ByteBufferUtil.bytes("col5")), ByteBufferUtil.bytes("updated"), 2L); - rm.apply(); - store.forceBlockingFlush(); - - cfam = store.getColumnFamily(QueryFilter.getNamesFilter(dk, new QueryPath(cfName), ByteBufferUtil.bytes("col5"))); - assert cfam.getColumnCount() == 1; - assert cfam.getColumn(ByteBufferUtil.bytes("col5")).value().equals( ByteBufferUtil.bytes("updated")); - } - - @Test - public void addNewKS() throws ConfigurationException, IOException, ExecutionException, InterruptedException - { - DecoratedKey dk = Util.dk("key0"); - CFMetaData newCf = addTestCF("NewKeyspace1", "AddedStandard1", "A new cf for a new ks"); - - KSMetaData newKs = new KSMetaData(newCf.tableName, SimpleStrategy.class, null, 5, newCf); - - new AddKeyspace(newKs).apply(); - - assert DatabaseDescriptor.getTableDefinition(newCf.tableName) != null; - assert DatabaseDescriptor.getTableDefinition(newCf.tableName) == newKs; - - // test reads and writes. - RowMutation rm = new RowMutation(newCf.tableName, dk.key); - rm.add(new QueryPath(newCf.cfName, null, ByteBufferUtil.bytes("col0")), ByteBufferUtil.bytes("value0"), 1L); - rm.apply(); - ColumnFamilyStore store = Table.open(newCf.tableName).getColumnFamilyStore(newCf.cfName); - assert store != null; - store.forceBlockingFlush(); - - ColumnFamily cfam = store.getColumnFamily(QueryFilter.getNamesFilter(dk, new QueryPath(newCf.cfName), ByteBufferUtil.bytes("col0"))); - assert cfam.getColumn(ByteBufferUtil.bytes("col0")) != null; - IColumn col = cfam.getColumn(ByteBufferUtil.bytes("col0")); - assert ByteBufferUtil.bytes("value0").equals(col.value()); - } - - @Test - public void dropKS() throws ConfigurationException, IOException, ExecutionException, InterruptedException - { - DecoratedKey dk = Util.dk("dropKs"); - // sanity - final KSMetaData ks = DatabaseDescriptor.getTableDefinition("Keyspace1"); - assert ks != null; - final CFMetaData cfm = ks.cfMetaData().get("Standard2"); - assert cfm != null; - - // write some data, force a flush, then verify that files exist on disk. - RowMutation rm = new RowMutation(ks.name, dk.key); - for (int i = 0; i < 100; i++) - rm.add(new QueryPath(cfm.cfName, null, ByteBufferUtil.bytes(("col" + i))), ByteBufferUtil.bytes("anyvalue"), 1L); - rm.apply(); - ColumnFamilyStore store = Table.open(cfm.tableName).getColumnFamilyStore(cfm.cfName); - assert store != null; - store.forceBlockingFlush(); - assert DefsTable.getFiles(cfm.tableName, cfm.cfName).size() > 0; - - new DropKeyspace(ks.name).apply(); - - assert DatabaseDescriptor.getTableDefinition(ks.name) == null; - - // write should fail. - rm = new RowMutation(ks.name, dk.key); - boolean success = true; - try - { - rm.add(new QueryPath("Standard1", null, ByteBufferUtil.bytes("col0")), ByteBufferUtil.bytes("value0"), 1L); - rm.apply(); - } - catch (Throwable th) - { - success = false; - } - assert !success : "This mutation should have failed since the CF no longer exists."; - - // reads should fail too. - try - { - Table.open(ks.name); - } - catch (Throwable th) - { - // this is what has historically happened when you try to open a table that doesn't exist. - assert th instanceof NullPointerException; - } - } - - @Test - public void dropKSUnflushed() throws ConfigurationException, IOException, ExecutionException, InterruptedException - { - DecoratedKey dk = Util.dk("dropKs"); - // sanity - final KSMetaData ks = DatabaseDescriptor.getTableDefinition("Keyspace3"); - assert ks != null; - final CFMetaData cfm = ks.cfMetaData().get("Standard1"); - assert cfm != null; - - // write some data - RowMutation rm = new RowMutation(ks.name, dk.key); - for (int i = 0; i < 100; i++) - rm.add(new QueryPath(cfm.cfName, null, ByteBufferUtil.bytes(("col" + i))), ByteBufferUtil.bytes("anyvalue"), 1L); - rm.apply(); - - new DropKeyspace(ks.name).apply(); - - assert DatabaseDescriptor.getTableDefinition(ks.name) == null; - } - - @Test - public void renameKs() throws ConfigurationException, IOException, ExecutionException, InterruptedException - { - DecoratedKey dk = Util.dk("renameKs"); - final KSMetaData oldKs = DatabaseDescriptor.getTableDefinition("Keyspace2"); - assert oldKs != null; - final String cfName = "Standard3"; - assert oldKs.cfMetaData().containsKey(cfName); - assert oldKs.cfMetaData().get(cfName).tableName.equals(oldKs.name); - - // write some data that we hope to read back later. - RowMutation rm = new RowMutation(oldKs.name, dk.key); - for (int i = 0; i < 10; i++) - rm.add(new QueryPath(cfName, null, ByteBufferUtil.bytes(("col" + i))), ByteBufferUtil.bytes("value"), 1L); - rm.apply(); - ColumnFamilyStore store = Table.open(oldKs.name).getColumnFamilyStore(cfName); - assert store != null; - store.forceBlockingFlush(); - assert DefsTable.getFiles(oldKs.name, cfName).size() > 0; - - final String newKsName = "RenamedKeyspace2"; - new RenameKeyspace(oldKs.name, newKsName).apply(); - KSMetaData newKs = DatabaseDescriptor.getTableDefinition(newKsName); - - assert DatabaseDescriptor.getTableDefinition(oldKs.name) == null; - assert newKs != null; - assert newKs.name.equals(newKsName); - assert newKs.cfMetaData().containsKey(cfName); - assert newKs.cfMetaData().get(cfName).tableName.equals(newKsName); - assert DefsTable.getFiles(newKs.name, cfName).size() > 0; - - // read on old should fail. - try - { - Table.open(oldKs.name); - } - catch (Throwable th) - { - assert th instanceof NullPointerException; - } - - // write on old should fail. - rm = new RowMutation(oldKs.name, ByteBufferUtil.bytes("any key will do")); - boolean success = true; - try - { - rm.add(new QueryPath(cfName, null, ByteBufferUtil.bytes("col0")), ByteBufferUtil.bytes("value0"), 1L); - rm.apply(); - } - catch (Throwable th) - { - success = false; - } - assert !success : "This mutation should have failed since the CF/Table no longer exists."; - - // write on new should work. - rm = new RowMutation(newKsName, dk.key); - rm.add(new QueryPath(cfName, null, ByteBufferUtil.bytes("col0")), ByteBufferUtil.bytes("newvalue"), 2L); - rm.apply(); - store = Table.open(newKs.name).getColumnFamilyStore(cfName); - assert store != null; - store.forceBlockingFlush(); - - // read on new should work. - SortedSet cols = new TreeSet(BytesType.instance); - cols.add(ByteBufferUtil.bytes("col0")); - cols.add(ByteBufferUtil.bytes("col1")); - ColumnFamily cfam = store.getColumnFamily(QueryFilter.getNamesFilter(dk, new QueryPath(cfName), cols)); - assert cfam.getColumnCount() == cols.size(); - // tests new write. - - ByteBuffer val = cfam.getColumn(ByteBufferUtil.bytes("col0")).value(); - assertEquals(ByteBufferUtil.string(val), "newvalue"); - // tests old write. - val = cfam.getColumn(ByteBufferUtil.bytes("col1")).value(); - assertEquals(ByteBufferUtil.string(val), "value"); - } - - @Test - public void createEmptyKsAddNewCf() throws ConfigurationException, IOException, ExecutionException, InterruptedException - { - assert DatabaseDescriptor.getTableDefinition("EmptyKeyspace") == null; - - KSMetaData newKs = new KSMetaData("EmptyKeyspace", SimpleStrategy.class, null, 5); - - new AddKeyspace(newKs).apply(); - assert DatabaseDescriptor.getTableDefinition("EmptyKeyspace") != null; - - CFMetaData newCf = addTestCF("EmptyKeyspace", "AddedLater", "A new CF to add to an empty KS"); - - //should not exist until apply - assert !DatabaseDescriptor.getTableDefinition(newKs.name).cfMetaData().containsKey(newCf.cfName); - - //add the new CF to the empty space - new AddColumnFamily(newCf).apply(); - - assert DatabaseDescriptor.getTableDefinition(newKs.name).cfMetaData().containsKey(newCf.cfName); - assert DatabaseDescriptor.getTableDefinition(newKs.name).cfMetaData().get(newCf.cfName).equals(newCf); - - // now read and write to it. - DecoratedKey dk = Util.dk("key0"); - RowMutation rm = new RowMutation(newKs.name, dk.key); - rm.add(new QueryPath(newCf.cfName, null, ByteBufferUtil.bytes("col0")), ByteBufferUtil.bytes("value0"), 1L); - rm.apply(); - ColumnFamilyStore store = Table.open(newKs.name).getColumnFamilyStore(newCf.cfName); - assert store != null; - store.forceBlockingFlush(); - - ColumnFamily cfam = store.getColumnFamily(QueryFilter.getNamesFilter(dk, new QueryPath(newCf.cfName), ByteBufferUtil.bytes("col0"))); - assert cfam.getColumn(ByteBufferUtil.bytes("col0")) != null; - IColumn col = cfam.getColumn(ByteBufferUtil.bytes("col0")); - assert ByteBufferUtil.bytes("value0").equals(col.value()); - } - - @Test - public void testUpdateKeyspace() throws ConfigurationException, IOException, ExecutionException, InterruptedException - { - // create a keyspace to serve as existing. - CFMetaData cf = addTestCF("UpdatedKeyspace", "AddedStandard1", "A new cf for a new ks"); - KSMetaData oldKs = new KSMetaData(cf.tableName, SimpleStrategy.class, null, 5, cf); - - new AddKeyspace(oldKs).apply(); - - assert DatabaseDescriptor.getTableDefinition(cf.tableName) != null; - assert DatabaseDescriptor.getTableDefinition(cf.tableName) == oldKs; - - // anything with cf defs should fail. - CFMetaData cf2 = addTestCF(cf.tableName, "AddedStandard2", "A new cf for a new ks"); - KSMetaData newBadKs = new KSMetaData(cf.tableName, SimpleStrategy.class, null, 4, cf2); - try - { - new UpdateKeyspace(newBadKs).apply(); - throw new AssertionError("Should not have been able to update a KS with a KS that described column families."); - } - catch (ConfigurationException ex) - { - // expected. - } - - // names should match. - KSMetaData newBadKs2 = new KSMetaData(cf.tableName + "trash", SimpleStrategy.class, null, 4); - try - { - new UpdateKeyspace(newBadKs2).apply(); - throw new AssertionError("Should not have been able to update a KS with an invalid KS name."); - } - catch (ConfigurationException ex) - { - // expected. - } - - KSMetaData newKs = new KSMetaData(cf.tableName, OldNetworkTopologyStrategy.class, null, 1); - new UpdateKeyspace(newKs).apply(); - - KSMetaData newFetchedKs = DatabaseDescriptor.getKSMetaData(newKs.name); - assert newFetchedKs.replicationFactor == newKs.replicationFactor; - assert newFetchedKs.replicationFactor != oldKs.replicationFactor; - assert newFetchedKs.strategyClass.equals(newKs.strategyClass); - assert !newFetchedKs.strategyClass.equals(oldKs.strategyClass); - } - - @Test - public void testUpdateColumnFamilyNoIndexes() throws ConfigurationException, IOException, ExecutionException, InterruptedException - { - // create a keyspace with a cf to update. - CFMetaData cf = addTestCF("UpdatedCfKs", "Standard1added", "A new cf that will be updated"); - KSMetaData ksm = new KSMetaData(cf.tableName, SimpleStrategy.class, null, 1, cf); - new AddKeyspace(ksm).apply(); - - assert DatabaseDescriptor.getTableDefinition(cf.tableName) != null; - assert DatabaseDescriptor.getTableDefinition(cf.tableName) == ksm; - assert DatabaseDescriptor.getCFMetaData(cf.tableName, cf.cfName) != null; - - // updating certain fields should fail. - org.apache.cassandra.avro.CfDef cf_def = CFMetaData.convertToAvro(cf); - cf_def.row_cache_size = 43.3; - cf_def.column_metadata = new ArrayList(); - cf_def.default_validation_class ="BytesType"; - cf_def.min_compaction_threshold = 5; - cf_def.max_compaction_threshold = 31; - - // test valid operations. - cf_def.comment = "Modified comment"; - new UpdateColumnFamily(cf_def).apply(); // doesn't get set back here. - - cf_def.row_cache_size = 2d; - new UpdateColumnFamily(cf_def).apply(); - - cf_def.key_cache_size = 3d; - new UpdateColumnFamily(cf_def).apply(); - - cf_def.read_repair_chance = 0.23; - new UpdateColumnFamily(cf_def).apply(); - - cf_def.gc_grace_seconds = 12; - new UpdateColumnFamily(cf_def).apply(); - - cf_def.default_validation_class = "UTF8Type"; - new UpdateColumnFamily(cf_def).apply(); - - cf_def.min_compaction_threshold = 3; - new UpdateColumnFamily(cf_def).apply(); - - cf_def.max_compaction_threshold = 33; - new UpdateColumnFamily(cf_def).apply(); - - // can't test changing the reconciler because there is only one impl. - - // check the cumulative affect. - assert DatabaseDescriptor.getCFMetaData(cf.tableName, cf.cfName).getComment().equals(cf_def.comment); - assert DatabaseDescriptor.getCFMetaData(cf.tableName, cf.cfName).getRowCacheSize() == cf_def.row_cache_size; - assert DatabaseDescriptor.getCFMetaData(cf.tableName, cf.cfName).getKeyCacheSize() == cf_def.key_cache_size; - assert DatabaseDescriptor.getCFMetaData(cf.tableName, cf.cfName).getReadRepairChance() == cf_def.read_repair_chance; - assert DatabaseDescriptor.getCFMetaData(cf.tableName, cf.cfName).getGcGraceSeconds() == cf_def.gc_grace_seconds; - assert DatabaseDescriptor.getCFMetaData(cf.tableName, cf.cfName).getDefaultValidator() == UTF8Type.instance; - - // todo: we probably don't need to reset old values in the catches anymore. - // make sure some invalid operations fail. - int oldId = cf_def.id; - try - { - cf_def.id++; - cf.apply(cf_def); - throw new AssertionError("Should have blown up when you used a different id."); - } - catch (ConfigurationException expected) - { - cf_def.id = oldId; - } - - CharSequence oldStr = cf_def.name; - try - { - cf_def.name = cf_def.name + "_renamed"; - cf.apply(cf_def); - throw new AssertionError("Should have blown up when you used a different name."); - } - catch (ConfigurationException expected) - { - cf_def.name = oldStr; - } - - oldStr = cf_def.keyspace; - try - { - cf_def.keyspace = oldStr + "_renamed"; - cf.apply(cf_def); - throw new AssertionError("Should have blown up when you used a different keyspace."); - } - catch (ConfigurationException expected) - { - cf_def.keyspace = oldStr; - } - - try - { - cf_def.column_type = ColumnFamilyType.Super.name(); - cf.apply(cf_def); - throw new AssertionError("Should have blwon up when you used a different cf type."); - } - catch (ConfigurationException expected) - { - cf_def.column_type = ColumnFamilyType.Standard.name(); - } - - oldStr = cf_def.comparator_type; - try - { - cf_def.comparator_type = BytesType.class.getSimpleName(); - cf.apply(cf_def); - throw new AssertionError("Should have blown up when you used a different comparator."); - } - catch (ConfigurationException expected) - { - cf_def.comparator_type = UTF8Type.class.getSimpleName(); - } - - try - { - cf_def.min_compaction_threshold = 34; - cf.apply(cf_def); - throw new AssertionError("Should have blown up when min > max."); - } - catch (ConfigurationException expected) - { - cf_def.min_compaction_threshold = 3; - } - - try - { - cf_def.max_compaction_threshold = 2; - cf.apply(cf_def); - throw new AssertionError("Should have blown up when max > min."); - } - catch (ConfigurationException expected) - { - cf_def.max_compaction_threshold = 33; - } - } - - private CFMetaData addTestCF(String ks, String cf, String comment) - { - return new CFMetaData(ks, - cf, - ColumnFamilyType.Standard, - UTF8Type.instance, - null, - comment, - 0, - 1.0, - 0, - CFMetaData.DEFAULT_GC_GRACE_SECONDS, - BytesType.instance, - CFMetaData.DEFAULT_MIN_COMPACTION_THRESHOLD, - CFMetaData.DEFAULT_MAX_COMPACTION_THRESHOLD, - CFMetaData.DEFAULT_ROW_CACHE_SAVE_PERIOD_IN_SECONDS, - CFMetaData.DEFAULT_KEY_CACHE_SAVE_PERIOD_IN_SECONDS, - CFMetaData.DEFAULT_MEMTABLE_LIFETIME_IN_MINS, - CFMetaData.DEFAULT_MEMTABLE_THROUGHPUT_IN_MB, - CFMetaData.DEFAULT_MEMTABLE_OPERATIONS_IN_MILLIONS, - Collections.emptyMap()); - } -}