This is an automated email from the ASF dual-hosted git repository. aweisberg pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/cassandra-dtest.git
The following commit(s) were added to refs/heads/master by this push: new 7a6d900 If SizeEstimatesRecorder misses a 'onDropTable' notification, the size_estimates table will never be cleared for that table 7a6d900 is described below commit 7a6d9002709628de2bc6af9d987a189b302e4472 Author: Joel Knighton <joel.knigh...@datastax.com> AuthorDate: Tue Sep 12 17:33:56 2017 -0500 If SizeEstimatesRecorder misses a 'onDropTable' notification, the size_estimates table will never be cleared for that table Patch by Joel Knighton; Reviewed by Ariel Weisberg for CASSANDRA-14905 Co-authored-by: Joel Knighton <j...@apache.org> Co-authored-by: Aleksandr Sorokoumov <aleksandr.sorokou...@gmail.com> --- nodetool_test.py | 20 ++++++++++++++++++ schema_test.py | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++-- tools/assertions.py | 19 +++++++++++++++-- 3 files changed, 96 insertions(+), 4 deletions(-) diff --git a/nodetool_test.py b/nodetool_test.py index fb73d30..012780b 100644 --- a/nodetool_test.py +++ b/nodetool_test.py @@ -300,6 +300,26 @@ class TestNodetool(Tester): session.execute('INSERT INTO test.test (pk, ck, val) VALUES (0, 1, 2);') assert_all(session, 'SELECT pk, ck, val FROM test.test;', [[0, 1, 2]]) + @since('3.0') + def test_refresh_size_estimates_clears_invalid_entries(self): + """ + @jira_ticket CASSANDRA-14905 + nodetool refreshsizeestimates should clear up entries for tables that no longer exist + """ + cluster = self.cluster + cluster.populate(1) + node = cluster.nodelist()[0] + cluster.start() + session = self.patient_exclusive_cql_connection(node) + session.execute("USE system;") + # Valid keyspace but invalid table + session.execute("INSERT INTO size_estimates (keyspace_name, table_name, range_start, range_end, mean_partition_size, partitions_count) VALUES ('system_auth', 'bad_table', '-5', '5', 0, 0);") + # Invalid keyspace and table + session.execute("INSERT INTO size_estimates (keyspace_name, table_name, range_start, range_end, mean_partition_size, partitions_count) VALUES ('bad_keyspace', 'bad_table', '-5', '5', 0, 0);") + node.nodetool('refreshsizeestimates') + assert_none(session, "SELECT * FROM size_estimates WHERE keyspace_name='system_auth' AND table_name='bad_table'") + assert_none(session, "SELECT * FROM size_estimates WHERE keyspace_name='bad_keyspace'") + @since('4.0') def test_set_get_concurrent_view_builders(self): """ diff --git a/schema_test.py b/schema_test.py index 8aaea3d..6c9f8a1 100644 --- a/schema_test.py +++ b/schema_test.py @@ -4,8 +4,8 @@ import logging from cassandra.concurrent import execute_concurrent_with_args -from tools.assertions import assert_invalid, assert_all, assert_one -from dtest import Tester, create_ks +from tools.assertions import assert_invalid, assert_all, assert_one, assert_none, assert_some +from dtest import Tester, create_ks, create_cf since = pytest.mark.since logger = logging.getLogger(__name__) @@ -176,6 +176,63 @@ class TestSchema(Tester): session.execute("USE ks") assert_all(session, "SELECT * FROM ts", [[1, 1, 'v1'], [1, 2, 'v2'], [2, 1, 'v3']]) + @since('3.0') + def drop_table_reflected_in_size_estimates_test(self): + """ + A dropped table should result in its entries being removed from size estimates, on both + nodes that are up and down at the time of the drop. + + @jira_ticket CASSANDRA-14905 + """ + cluster = self.cluster + cluster.populate(2).start() + node1, node2 = cluster.nodelist() + session = self.patient_exclusive_cql_connection(node1) + create_ks(session, 'ks1', 2) + create_ks(session, 'ks2', 2) + create_cf(session, 'ks1.cf1', columns={'c1': 'text', 'c2': 'text'}) + create_cf(session, 'ks2.cf1', columns={'c1': 'text', 'c2': 'text'}) + create_cf(session, 'ks2.cf2', columns={'c1': 'text', 'c2': 'text'}) + + node1.nodetool('refreshsizeestimates') + node2.nodetool('refreshsizeestimates') + node2.stop() + session.execute('DROP TABLE ks2.cf1') + session.execute('DROP KEYSPACE ks1') + node2.start(wait_for_binary_proto=True) + session2 = self.patient_exclusive_cql_connection(node2) + + session.cluster.control_connection.wait_for_schema_agreement() + + assert_none(session, "SELECT * FROM system.size_estimates WHERE keyspace_name='ks1'") + assert_none(session, "SELECT * FROM system.size_estimates WHERE keyspace_name='ks2' AND table_name='cf1'") + assert_some(session, "SELECT * FROM system.size_estimates WHERE keyspace_name='ks2' AND table_name='cf2'") + assert_none(session2, "SELECT * FROM system.size_estimates WHERE keyspace_name='ks1'") + assert_none(session2, "SELECT * FROM system.size_estimates WHERE keyspace_name='ks2' AND table_name='cf1'") + assert_some(session, "SELECT * FROM system.size_estimates WHERE keyspace_name='ks2' AND table_name='cf2'") + + @since('3.0') + def invalid_entries_removed_from_size_estimates_on_restart_test(self): + """ + Entries for dropped tables/keyspaces should be cleared from size_estimates on restart. + + @jira_ticket CASSANDRA-14905 + """ + cluster = self.cluster + cluster.populate(1).start() + node = cluster.nodelist()[0] + session = self.patient_cql_connection(node) + session.execute("USE system;") + session.execute("INSERT INTO size_estimates (keyspace_name, table_name, range_start, range_end, mean_partition_size, partitions_count) VALUES ( 'system_auth', 'bad_table', '-5', '5', 0, 0);") + # Invalid keyspace and table + session.execute("INSERT INTO size_estimates (keyspace_name, table_name, range_start, range_end, mean_partition_size, partitions_count) VALUES ( 'bad_keyspace', 'bad_table', '-5', '5', 0, 0);") + node.stop() + node.start() + session = self.patient_cql_connection(node) + assert_none(session, "SELECT * FROM system.size_estimates WHERE keyspace_name='system_auth' AND table_name='bad_table'") + assert_none(session, "SELECT * FROM system.size_estimates WHERE keyspace_name='bad_keyspace'") + + def prepare(self): cluster = self.cluster cluster.populate(1).start() diff --git a/tools/assertions.py b/tools/assertions.py index bce9b8a..d91e6fd 100644 --- a/tools/assertions.py +++ b/tools/assertions.py @@ -8,8 +8,8 @@ from cassandra.query import SimpleStatement """ -The assertion methods in this file are used to structure, execute, and test different queries and scenarios. -Use these anytime you are trying to check the content of a table, the row count of a table, if a query should +The assertion methods in this file are used to structure, execute, and test different queries and scenarios. +Use these anytime you are trying to check the content of a table, the row count of a table, if a query should raise an exception, etc. These methods handle error messaging well, and will help discovering and treating bugs. An example: @@ -149,6 +149,21 @@ def assert_none(session, query, cl=None): assert list_res == [], "Expected nothing from {}, but got {}".format(query, list_res) +def assert_some(session, query, cl=None, execution_profile=None): + """ + Assert query returns something + @param session Session to use + @param query Query to run + @param cl Optional Consistency Level setting. Default ONE + Examples: + assert_some(self.session1, "SELECT * FROM test where key=2;") + assert_some(cursor, "SELECT * FROM test WHERE k=2", cl=ConsistencyLevel.SERIAL) + """ + res = _execute(session, query, cl=cl, execution_profile=execution_profile) + list_res = _rows_to_list(res) + assert list_res != [], "Expected something from {}, but got {}".format(query, list_res) + + def assert_all(session, query, expected, cl=None, ignore_order=False, timeout=None): """ Assert query returns all expected items optionally in the correct order --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org