You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cassandra.apache.org by mc...@apache.org on 2020/05/14 07:37:13 UTC

[cassandra] branch trunk updated: Fix clearing of legacy size_estimates

This is an automated email from the ASF dual-hosted git repository.

mck pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/cassandra.git


The following commit(s) were added to refs/heads/trunk by this push:
     new 0110311  Fix clearing of legacy size_estimates
0110311 is described below

commit 01103111ae08b51ccd18bb1c54ac60546546d9df
Author: David Capwell <dc...@apple.com>
AuthorDate: Wed Apr 29 12:31:27 2020 -0700

    Fix clearing of legacy size_estimates
    
     patch by David Capwell; reviewed by Eduard Tudenhöfner, Dinesh Joshi, Mick Semb Wever for CASSANDRA-15776
---
 CHANGES.txt                                        |  1 +
 .../org/apache/cassandra/db/SystemKeyspace.java    | 25 ++-----
 .../apache/cassandra/service/StorageService.java   | 19 +----
 .../distributed/test/TableEstimatesTest.java       | 84 ++++++++++++++++++++++
 .../apache/cassandra/tools/ClearSnapshotTest.java  |  4 ++
 5 files changed, 95 insertions(+), 38 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index 98b3f68..f430f5c 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 4.0-alpha5
+ * Fix clearing of legacy size_estimates (CASSANDRA-15776)
  * Update port when reconnecting to pre-4.0 SSL storage (CASSANDRA-15727)
  * Only calculate dynamicBadnessThreshold once per loop in DynamicEndpointSnitch (CASSANDRA-15798)
  * Cleanup redundant nodetool commands added in 4.0 (CASSANDRA-15256)
diff --git a/src/java/org/apache/cassandra/db/SystemKeyspace.java b/src/java/org/apache/cassandra/db/SystemKeyspace.java
index eb31f2d..655c7a0 100644
--- a/src/java/org/apache/cassandra/db/SystemKeyspace.java
+++ b/src/java/org/apache/cassandra/db/SystemKeyspace.java
@@ -1327,30 +1327,15 @@ public final class SystemKeyspace
     }
 
     /**
-     * Clears size estimates for a keyspace (used to manually clean when we miss a keyspace drop)
+     * truncates size_estimates and table_estimates tables
      */
-    public static void clearEstimates(String keyspace)
+    public static void clearAllEstimates()
     {
-        String cqlFormat = "DELETE FROM %s WHERE keyspace_name = ?";
-        String cql = String.format(cqlFormat, LegacySizeEstimates.toString());
-        executeInternal(cql, keyspace);
-        cql = String.format(cqlFormat, TableEstimates.toString());
-        executeInternal(cql, keyspace);
-    }
-
-    /**
-     * @return A multimap from keyspace to table for all tables with entries in size estimates
-     */
-    public static synchronized SetMultimap<String, String> getTablesWithSizeEstimates()
-    {
-        SetMultimap<String, String> keyspaceTableMap = HashMultimap.create();
-        String cql = String.format("SELECT keyspace_name, table_name FROM %s", TableEstimates.toString(), TABLE_ESTIMATES_TYPE_PRIMARY);
-        UntypedResultSet rs = executeInternal(cql);
-        for (UntypedResultSet.Row row : rs)
+        for (TableMetadata table : Arrays.asList(LegacySizeEstimates, TableEstimates))
         {
-            keyspaceTableMap.put(row.getString("keyspace_name"), row.getString("table_name"));
+            String cql = String.format("TRUNCATE TABLE " + table.toString());
+            executeInternal(cql);
         }
-        return keyspaceTableMap;
     }
 
     public static synchronized void updateAvailableRanges(String keyspace, Collection<Range<Token>> completedFullRanges, Collection<Range<Token>> completedTransientRanges)
diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java
index 38da4e8..dfc1da9 100644
--- a/src/java/org/apache/cassandra/service/StorageService.java
+++ b/src/java/org/apache/cassandra/service/StorageService.java
@@ -3670,24 +3670,7 @@ public class StorageService extends NotificationBroadcasterSupport implements IE
 
     public void cleanupSizeEstimates()
     {
-        SetMultimap<String, String> sizeEstimates = SystemKeyspace.getTablesWithSizeEstimates();
-
-        for (Entry<String, Collection<String>> tablesByKeyspace : sizeEstimates.asMap().entrySet())
-        {
-            String keyspace = tablesByKeyspace.getKey();
-            if (!Schema.instance.getKeyspaces().contains(keyspace))
-            {
-                SystemKeyspace.clearEstimates(keyspace);
-            }
-            else
-            {
-                for (String table : tablesByKeyspace.getValue())
-                {
-                    if (Schema.instance.getTableMetadataRef(keyspace, table) == null)
-                        SystemKeyspace.clearEstimates(keyspace, table);
-                }
-            }
-        }
+        SystemKeyspace.clearAllEstimates();
     }
 
     /**
diff --git a/test/distributed/org/apache/cassandra/distributed/test/TableEstimatesTest.java b/test/distributed/org/apache/cassandra/distributed/test/TableEstimatesTest.java
new file mode 100644
index 0000000..0130f28
--- /dev/null
+++ b/test/distributed/org/apache/cassandra/distributed/test/TableEstimatesTest.java
@@ -0,0 +1,84 @@
+package org.apache.cassandra.distributed.test;
+
+import java.io.IOException;
+
+import org.junit.AfterClass;
+import org.junit.Assume;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.cassandra.distributed.Cluster;
+import org.apache.cassandra.distributed.api.ConsistencyLevel;
+import org.apache.cassandra.distributed.api.IInstance;
+import org.apache.cassandra.distributed.api.QueryResult;
+import org.assertj.core.api.Assertions;
+
+public class TableEstimatesTest extends TestBaseImpl
+{
+    private static Cluster CLUSTER;
+
+    @BeforeClass
+    public static void setupCluster() throws IOException
+    {
+        CLUSTER = init(Cluster.build(1).start());
+    }
+
+    @AfterClass
+    public static void teardownCluster()
+    {
+        if (CLUSTER != null)
+            CLUSTER.close();
+    }
+
+    /**
+     * Replaces Python Dtest: nodetool_test.py#test_refresh_size_estimates_clears_invalid_entries
+     */
+    @Test
+    public void refreshTableEstimatesClearsInvalidEntries()
+    {
+        String table_estimatesInsert = "INSERT INTO system.table_estimates (keyspace_name, table_name, range_type, range_start, range_end, mean_partition_size, partitions_count) VALUES (?, ?, ?, ?, ?, ?, ?)";
+        IInstance node = CLUSTER.get(1);
+
+        try
+        {
+            node.executeInternal(table_estimatesInsert, "system_auth", "bad_table", "local_primary", "-5", "5", 0L, 0L);
+            node.executeInternal(table_estimatesInsert, "bad_keyspace", "bad_table", "local_primary", "-5", "5", 0L, 0L);
+        }
+        catch (Exception e)
+        {
+            // to make this test portable (with the intent to extract out), handle the case where the table_estimates isn't defined
+            Assertions.assertThat(e.getClass().getCanonicalName()).isEqualTo("org.apache.cassandra.exceptions.InvalidRequestException");
+            Assertions.assertThat(e).hasMessageContaining("does not exist");
+            Assume.assumeTrue("system.table_estimates not present", false);
+        }
+
+        node.nodetoolResult("refreshsizeestimates").asserts().success();
+
+        QueryResult qr = CLUSTER.coordinator(1).executeWithResult("SELECT * FROM system.table_estimates WHERE keyspace_name=? AND table_name=?", ConsistencyLevel.ONE, "system_auth", "bad_table");
+        Assertions.assertThat(qr).isExhausted();
+
+        qr = CLUSTER.coordinator(1).executeWithResult("SELECT * FROM system.table_estimates WHERE keyspace_name=?", ConsistencyLevel.ONE, "bad_keyspace");
+        Assertions.assertThat(qr).isExhausted();
+    }
+
+    /**
+     * Replaces Python Dtest: nodetool_test.py#test_refresh_size_estimates_clears_invalid_entries
+     */
+    @Test
+    public void refreshSizeEstimatesClearsInvalidEntries()
+    {
+        String size_estimatesInsert = "INSERT INTO system.size_estimates (keyspace_name, table_name, range_start, range_end, mean_partition_size, partitions_count) VALUES (?, ?, ?, ?, ?, ?)";
+        IInstance node = CLUSTER.get(1);
+
+        node.executeInternal(size_estimatesInsert, "system_auth", "bad_table", "-5", "5", 0L, 0L);
+        node.executeInternal(size_estimatesInsert, "bad_keyspace", "bad_table", "-5", "5", 0L, 0L);
+
+        node.nodetoolResult("refreshsizeestimates").asserts().success();
+
+        QueryResult qr = CLUSTER.coordinator(1).executeWithResult("SELECT * FROM system.size_estimates WHERE keyspace_name=? AND table_name=?", ConsistencyLevel.ONE, "system_auth", "bad_table");
+        Assertions.assertThat(qr).isExhausted();
+
+        qr = CLUSTER.coordinator(1).executeWithResult("SELECT * FROM system.size_estimates WHERE keyspace_name=?", ConsistencyLevel.ONE, "bad_keyspace");
+        Assertions.assertThat(qr).isExhausted();
+    }
+}
diff --git a/test/unit/org/apache/cassandra/tools/ClearSnapshotTest.java b/test/unit/org/apache/cassandra/tools/ClearSnapshotTest.java
index 6b132ab..a73493b 100644
--- a/test/unit/org/apache/cassandra/tools/ClearSnapshotTest.java
+++ b/test/unit/org/apache/cassandra/tools/ClearSnapshotTest.java
@@ -29,6 +29,7 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 import org.apache.cassandra.SchemaLoader;
+import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.service.EmbeddedCassandraService;
 
 public class ClearSnapshotTest extends ToolsTester
@@ -46,6 +47,9 @@ public class ClearSnapshotTest extends ToolsTester
         System.setProperty("cassandra.jmx.local.port", String.valueOf(JMX_PORT));
 
         SchemaLoader.prepareServer();
+        // CASSANDRA-15776 - size_estimates and table_estimates get truncated on startup, and auto snapshot is true by default for tests
+        // set it false so the test state doesn't see those snapshots
+        DatabaseDescriptor.setAutoSnapshot(false);
         cassandra = new EmbeddedCassandraService();
         cassandra.start();
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cassandra.apache.org
For additional commands, e-mail: commits-help@cassandra.apache.org