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

edimitrova 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 458bfd16c7 Add information info whether sstables are dropped or not to 
SchemaChangeListener patch by Jacek Lewandowski; reviewed by Alex Petrov for 
CASSANDRA-17582
458bfd16c7 is described below

commit 458bfd16c7ec759705f920e7ef9a8f2bb5a3f4b5
Author: Jacek Lewandowski <[email protected]>
AuthorDate: Tue Apr 26 14:43:49 2022 +0200

    Add information info whether sstables are dropped or not to 
SchemaChangeListener
    patch by Jacek Lewandowski; reviewed by Alex Petrov for CASSANDRA-17582
---
 CHANGES.txt                                        |   1 +
 .../cassandra/auth/AuthSchemaChangeListener.java   |   4 +-
 .../org/apache/cassandra/cql3/QueryProcessor.java  |   4 +-
 .../apache/cassandra/db/SizeEstimatesRecorder.java |   2 +-
 src/java/org/apache/cassandra/schema/Schema.java   |   4 +-
 .../cassandra/schema/SchemaChangeListener.java     |   8 +-
 .../cassandra/schema/SchemaChangeNotifier.java     |  26 ++---
 .../schema/SchemaUpdateHandlerFactoryProvider.java |   2 +-
 .../org/apache/cassandra/transport/Server.java     |   4 +-
 .../schema/RemoveWithoutDroppingTest.java          | 121 +++++++++++++++++++++
 .../transport/ClientNotificiationsTest.java        |   2 +-
 11 files changed, 150 insertions(+), 28 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index b0c0ba4f97..8ad715c1b9 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 4.1
+ * Add information whether sstables are dropped to SchemaChangeListener 
(CASSANDRA-17582)
  * Add a pluggable memtable API (CEP-11 / CASSANDRA-17034)
  * Save sstable id as string in activity table (CASSANDRA-17585)
  * Implement startup check to prevent Cassandra to potentially spread zombie 
data (CASSANDRA-17180)
diff --git a/src/java/org/apache/cassandra/auth/AuthSchemaChangeListener.java 
b/src/java/org/apache/cassandra/auth/AuthSchemaChangeListener.java
index 634d8f3de6..88a294000c 100644
--- a/src/java/org/apache/cassandra/auth/AuthSchemaChangeListener.java
+++ b/src/java/org/apache/cassandra/auth/AuthSchemaChangeListener.java
@@ -30,7 +30,7 @@ import org.apache.cassandra.schema.TableMetadata;
 public class AuthSchemaChangeListener implements SchemaChangeListener
 {
     @Override
-    public void onDropKeyspace(KeyspaceMetadata keyspace)
+    public void onDropKeyspace(KeyspaceMetadata keyspace, boolean dropData)
     {
         
DatabaseDescriptor.getAuthorizer().revokeAllOn(DataResource.keyspace(keyspace.name));
         
DatabaseDescriptor.getAuthorizer().revokeAllOn(DataResource.allTables(keyspace.name));
@@ -38,7 +38,7 @@ public class AuthSchemaChangeListener implements 
SchemaChangeListener
     }
 
     @Override
-    public void onDropTable(TableMetadata table)
+    public void onDropTable(TableMetadata table, boolean dropData)
     {
         
DatabaseDescriptor.getAuthorizer().revokeAllOn(DataResource.table(table.keyspace,
 table.name));
     }
diff --git a/src/java/org/apache/cassandra/cql3/QueryProcessor.java 
b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
index 2c8ce2f1c8..e14bfacd1e 100644
--- a/src/java/org/apache/cassandra/cql3/QueryProcessor.java
+++ b/src/java/org/apache/cassandra/cql3/QueryProcessor.java
@@ -1054,14 +1054,14 @@ public class QueryProcessor implements QueryHandler
         }
 
         @Override
-        public void onDropKeyspace(KeyspaceMetadata keyspace)
+        public void onDropKeyspace(KeyspaceMetadata keyspace, boolean dropData)
         {
             logger.trace("Keyspace {} was dropped, invalidating related 
prepared statements", keyspace.name);
             removeInvalidPreparedStatements(keyspace.name, null);
         }
 
         @Override
-        public void onDropTable(TableMetadata table)
+        public void onDropTable(TableMetadata table, boolean dropData)
         {
             logger.trace("Table {}.{} was dropped, invalidating related 
prepared statements", table.keyspace, table.name);
             removeInvalidPreparedStatements(table.keyspace, table.name);
diff --git a/src/java/org/apache/cassandra/db/SizeEstimatesRecorder.java 
b/src/java/org/apache/cassandra/db/SizeEstimatesRecorder.java
index cbd21da0f4..dfd52c5f38 100644
--- a/src/java/org/apache/cassandra/db/SizeEstimatesRecorder.java
+++ b/src/java/org/apache/cassandra/db/SizeEstimatesRecorder.java
@@ -178,7 +178,7 @@ public class SizeEstimatesRecorder implements 
SchemaChangeListener, Runnable
     }
 
     @Override
-    public void onDropTable(TableMetadata table)
+    public void onDropTable(TableMetadata table, boolean dropData)
     {
         SystemKeyspace.clearEstimates(table.keyspace, table.name);
     }
diff --git a/src/java/org/apache/cassandra/schema/Schema.java 
b/src/java/org/apache/cassandra/schema/Schema.java
index 5f21dbbb63..f89f8d5110 100644
--- a/src/java/org/apache/cassandra/schema/Schema.java
+++ b/src/java/org/apache/cassandra/schema/Schema.java
@@ -672,7 +672,7 @@ public class Schema implements SchemaProvider
             Keyspace.open(delta.after.name, this, 
true).viewManager.reload(true);
         }
 
-        schemaChangeNotifier.notifyKeyspaceAltered(delta);
+        schemaChangeNotifier.notifyKeyspaceAltered(delta, dropData);
         SchemaDiagnostics.keyspaceAltered(this, delta);
     }
 
@@ -721,7 +721,7 @@ public class Schema implements SchemaProvider
             Keyspace.writeOrder.awaitNewBarrier();
         }
 
-        schemaChangeNotifier.notifyKeyspaceDropped(keyspace);
+        schemaChangeNotifier.notifyKeyspaceDropped(keyspace, dropData);
         SchemaDiagnostics.keyspaceDropped(this, keyspace);
     }
 
diff --git a/src/java/org/apache/cassandra/schema/SchemaChangeListener.java 
b/src/java/org/apache/cassandra/schema/SchemaChangeListener.java
index f8661437ce..55fa25f49e 100644
--- a/src/java/org/apache/cassandra/schema/SchemaChangeListener.java
+++ b/src/java/org/apache/cassandra/schema/SchemaChangeListener.java
@@ -83,17 +83,17 @@ public interface SchemaChangeListener
     {
     }
 
-    default void onDropKeyspace(KeyspaceMetadata keyspace)
+    default void onDropKeyspace(KeyspaceMetadata keyspace, boolean dropData)
     {
     }
 
-    default void onDropTable(TableMetadata table)
+    default void onDropTable(TableMetadata table, boolean dropData)
     {
     }
 
-    default void onDropView(ViewMetadata view)
+    default void onDropView(ViewMetadata view, boolean dropData)
     {
-        onDropTable(view.metadata);
+        onDropTable(view.metadata, dropData);
     }
 
     default void onDropType(UserType type)
diff --git a/src/java/org/apache/cassandra/schema/SchemaChangeNotifier.java 
b/src/java/org/apache/cassandra/schema/SchemaChangeNotifier.java
index 2cb52167da..c4537e1999 100644
--- a/src/java/org/apache/cassandra/schema/SchemaChangeNotifier.java
+++ b/src/java/org/apache/cassandra/schema/SchemaChangeNotifier.java
@@ -56,13 +56,13 @@ public class SchemaChangeNotifier
         keyspace.functions.udas().forEach(this::notifyCreateAggregate);
     }
 
-    public void notifyKeyspaceAltered(KeyspaceMetadata.KeyspaceDiff delta)
+    public void notifyKeyspaceAltered(KeyspaceMetadata.KeyspaceDiff delta, 
boolean dropData)
     {
         // notify on everything dropped
         delta.udas.dropped.forEach(uda -> notifyDropAggregate((UDAggregate) 
uda));
         delta.udfs.dropped.forEach(udf -> notifyDropFunction((UDFunction) 
udf));
-        delta.views.dropped.forEach(this::notifyDropView);
-        delta.tables.dropped.forEach(this::notifyDropTable);
+        delta.views.dropped.forEach(view -> notifyDropView(view, dropData));
+        delta.tables.dropped.forEach(metadata -> notifyDropTable(metadata, 
dropData));
         delta.types.dropped.forEach(this::notifyDropType);
 
         // notify on everything created
@@ -82,14 +82,14 @@ public class SchemaChangeNotifier
         delta.udas.altered.forEach(diff -> notifyAlterAggregate(diff.before, 
diff.after));
     }
 
-    public void notifyKeyspaceDropped(KeyspaceMetadata keyspace)
+    public void notifyKeyspaceDropped(KeyspaceMetadata keyspace, boolean 
dropData)
     {
         keyspace.functions.udas().forEach(this::notifyDropAggregate);
         keyspace.functions.udfs().forEach(this::notifyDropFunction);
-        keyspace.views.forEach(this::notifyDropView);
-        keyspace.tables.forEach(this::notifyDropTable);
+        keyspace.views.forEach(view -> notifyDropView(view, dropData));
+        keyspace.tables.forEach(metadata -> notifyDropTable(metadata, 
dropData));
         keyspace.types.forEach(this::notifyDropType);
-        notifyDropKeyspace(keyspace);
+        notifyDropKeyspace(keyspace, dropData);
     }
 
     public void notifyPreChanges(SchemaTransformationResult 
transformationResult)
@@ -175,19 +175,19 @@ public class SchemaChangeNotifier
         changeListeners.forEach(l -> l.onAlterAggregate(before, after));
     }
 
-    private void notifyDropKeyspace(KeyspaceMetadata ksm)
+    private void notifyDropKeyspace(KeyspaceMetadata ksm, boolean dropData)
     {
-        changeListeners.forEach(l -> l.onDropKeyspace(ksm));
+        changeListeners.forEach(l -> l.onDropKeyspace(ksm, dropData));
     }
 
-    private void notifyDropTable(TableMetadata metadata)
+    private void notifyDropTable(TableMetadata metadata, boolean dropData)
     {
-        changeListeners.forEach(l -> l.onDropTable(metadata));
+        changeListeners.forEach(l -> l.onDropTable(metadata, dropData));
     }
 
-    private void notifyDropView(ViewMetadata view)
+    private void notifyDropView(ViewMetadata view, boolean dropData)
     {
-        changeListeners.forEach(l -> l.onDropView(view));
+        changeListeners.forEach(l -> l.onDropView(view, dropData));
     }
 
     private void notifyDropType(UserType ut)
diff --git 
a/src/java/org/apache/cassandra/schema/SchemaUpdateHandlerFactoryProvider.java 
b/src/java/org/apache/cassandra/schema/SchemaUpdateHandlerFactoryProvider.java
index 3ee2851003..9411a9285c 100644
--- 
a/src/java/org/apache/cassandra/schema/SchemaUpdateHandlerFactoryProvider.java
+++ 
b/src/java/org/apache/cassandra/schema/SchemaUpdateHandlerFactoryProvider.java
@@ -31,7 +31,7 @@ import org.apache.cassandra.utils.FBUtilities;
  */
 public class SchemaUpdateHandlerFactoryProvider implements 
Provider<SchemaUpdateHandlerFactory>
 {
-    private static final String SUH_FACTORY_CLASS_PROPERTY = 
"cassandra.schema.update_handler_factory.class";
+    public static final String SUH_FACTORY_CLASS_PROPERTY = 
"cassandra.schema.update_handler_factory.class";
 
     public final static SchemaUpdateHandlerFactoryProvider instance = new 
SchemaUpdateHandlerFactoryProvider();
 
diff --git a/src/java/org/apache/cassandra/transport/Server.java 
b/src/java/org/apache/cassandra/transport/Server.java
index ac1af4e5db..5ec6d20187 100644
--- a/src/java/org/apache/cassandra/transport/Server.java
+++ b/src/java/org/apache/cassandra/transport/Server.java
@@ -541,13 +541,13 @@ public class Server implements CassandraDaemon.Server
         }
 
         @Override
-        public void onDropKeyspace(KeyspaceMetadata keyspace)
+        public void onDropKeyspace(KeyspaceMetadata keyspace, boolean dropData)
         {
             send(new Event.SchemaChange(Event.SchemaChange.Change.DROPPED, 
keyspace.name));
         }
 
         @Override
-        public void onDropTable(TableMetadata table)
+        public void onDropTable(TableMetadata table, boolean dropData)
         {
             send(new Event.SchemaChange(Event.SchemaChange.Change.DROPPED, 
Event.SchemaChange.Target.TABLE, table.keyspace, table.name));
         }
diff --git 
a/test/unit/org/apache/cassandra/schema/RemoveWithoutDroppingTest.java 
b/test/unit/org/apache/cassandra/schema/RemoveWithoutDroppingTest.java
new file mode 100644
index 0000000000..9c3271bd69
--- /dev/null
+++ b/test/unit/org/apache/cassandra/schema/RemoveWithoutDroppingTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.Arrays;
+import java.util.List;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.stream.Collectors;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.cassandra.cql3.CQLTester;
+import org.apache.cassandra.db.ColumnFamilyStore;
+import org.apache.cassandra.io.util.File;
+import 
org.apache.cassandra.schema.SchemaTransformation.SchemaTransformationResult;
+import org.mockito.Mockito;
+
+import static org.apache.cassandra.cql3.QueryProcessor.executeInternal;
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class RemoveWithoutDroppingTest
+{
+    static volatile boolean dropDataOverride = true;
+
+    static final SchemaChangeListener listener = 
Mockito.mock(SchemaChangeListener.class);
+
+    @BeforeClass
+    public static void beforeClass()
+    {
+        
System.setProperty(SchemaUpdateHandlerFactoryProvider.SUH_FACTORY_CLASS_PROPERTY,
 TestSchemaUpdateHandlerFactory.class.getName());
+        CQLTester.prepareServer();
+        Schema.instance.registerListener(listener);
+    }
+
+    @Before
+    public void before()
+    {
+        Mockito.reset(listener);
+    }
+
+    public static void callbackOverride(BiConsumer<SchemaTransformationResult, 
Boolean> updateSchemaCallback, SchemaTransformationResult result, boolean 
dropData)
+    {
+        updateSchemaCallback.accept(result, dropDataOverride);
+    }
+
+    public static class TestSchemaUpdateHandlerFactory implements 
SchemaUpdateHandlerFactory
+    {
+        @Override
+        public SchemaUpdateHandler getSchemaUpdateHandler(boolean online, 
BiConsumer<SchemaTransformationResult, Boolean> updateSchemaCallback)
+        {
+            return online
+                   ? new DefaultSchemaUpdateHandler((result, dropData) -> 
callbackOverride(updateSchemaCallback, result, dropData))
+                   : new OfflineSchemaUpdateHandler((result, dropData) -> 
callbackOverride(updateSchemaCallback, result, dropData));
+        }
+    }
+
+    private void testRemoveKeyspace(String ks, String tab, boolean 
expectDropped) throws Throwable
+    {
+        executeInternal(String.format("CREATE KEYSPACE IF NOT EXISTS %s WITH 
replication = {'class': 'SimpleStrategy', 'replication_factor': '1'}", ks));
+        executeInternal(String.format("CREATE TABLE %s.%s (id INT PRIMARY KEY, 
v INT)", ks, tab));
+        executeInternal(String.format("INSERT INTO %s.%s (id, v) VALUES (?, 
?)", ks, tab), 1, 2);
+        executeInternal(String.format("INSERT INTO %s.%s (id, v) VALUES (?, 
?)", ks, tab), 3, 4);
+        ColumnFamilyStore cfs = ColumnFamilyStore.getIfExists(ks, tab);
+        cfs.forceFlush(ColumnFamilyStore.FlushReason.UNIT_TESTS).get();
+
+        KeyspaceMetadata ksm = Schema.instance.getKeyspaceMetadata(ks);
+        TableMetadata tm = Schema.instance.getTableMetadata(ks, tab);
+
+        List<File> directories = cfs.getDirectories().getCFDirectories();
+        Set<File> filesBefore = directories.stream().flatMap(d -> 
Arrays.stream(d.tryList(f -> !f.isDirectory()))).collect(Collectors.toSet());
+        assertThat(filesBefore).isNotEmpty();
+
+        executeInternal(String.format("DROP KEYSPACE %s", ks));
+
+        Set<File> filesAfter = directories.stream().flatMap(d -> 
Arrays.stream(d.tryList(f -> !f.isDirectory()))).collect(Collectors.toSet());
+        if (expectDropped)
+            assertThat(filesAfter).isEmpty();
+        else
+            assertThat(filesAfter).hasSameElementsAs(filesBefore);
+
+        Mockito.verify(listener).onDropTable(tm, expectDropped);
+        Mockito.verify(listener).onDropKeyspace(ksm, expectDropped);
+    }
+
+    @Test
+    public void testRemoveWithoutDropping() throws Throwable
+    {
+        dropDataOverride = false;
+        String ks = "test_remove_without_dropping";
+        String tab = "test_table";
+        testRemoveKeyspace(ks, tab, false);
+    }
+
+    @Test
+    public void testRemoveWithDropping() throws Throwable
+    {
+        dropDataOverride = true;
+        String ks = "test_remove_with_dropping";
+        String tab = "test_table";
+        testRemoveKeyspace(ks, tab, true);
+    }
+}
diff --git 
a/test/unit/org/apache/cassandra/transport/ClientNotificiationsTest.java 
b/test/unit/org/apache/cassandra/transport/ClientNotificiationsTest.java
index a130e3a234..9f95784e43 100644
--- a/test/unit/org/apache/cassandra/transport/ClientNotificiationsTest.java
+++ b/test/unit/org/apache/cassandra/transport/ClientNotificiationsTest.java
@@ -88,7 +88,7 @@ public class ClientNotificiationsTest extends CQLTester
             notifier.onLeaveCluster(broadcastAddress);
             notifier.onCreateKeyspace(ks);
             notifier.onAlterKeyspace(ks, ks);
-            notifier.onDropKeyspace(ks);
+            notifier.onDropKeyspace(ks, true);
 
             handler.assertNextEvent(Event.StatusChange.nodeUp(nativeAddress));
             
handler.assertNextEvent(Event.StatusChange.nodeDown(nativeAddress));


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to