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

jmckenzie 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 e89b214d06 Allow disabling hotness persistence for high sstable counts
e89b214d06 is described below

commit e89b214d069321c8968871b8eb7d51d4dfba7c33
Author: Josh McKenzie <jmcken...@apache.org>
AuthorDate: Tue Sep 13 12:48:00 2022 -0400

    Allow disabling hotness persistence for high sstable counts
    
    Patch by Caleb Rackliffe; reviewed by Chris Lohfink and Josh McKenzie for 
CASSANDRA-17868
    
    Co-authored-by: Caleb Rackliffe <calebrackli...@gmail.com>
    Co-authored-by: Josh McKenzie <jmcken...@apache.org>
---
 CHANGES.txt                                        |  1 +
 src/java/org/apache/cassandra/config/Config.java   |  2 +
 .../cassandra/config/DatabaseDescriptor.java       | 14 +++++
 .../org/apache/cassandra/db/SystemKeyspace.java    | 11 +++-
 .../cassandra/io/sstable/format/SSTableReader.java | 25 +++++----
 .../org/apache/cassandra/service/StorageProxy.java | 12 ++++
 .../cassandra/service/StorageProxyMBean.java       |  3 +
 .../cassandra/io/sstable/SSTableReaderTest.java    | 64 ++++++++++++++++------
 8 files changed, 103 insertions(+), 29 deletions(-)

diff --git a/CHANGES.txt b/CHANGES.txt
index 10830cedb0..49858daa9a 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
 4.2
+ * Allow disabling hotness persistence for high sstable counts 
(CASSANDRA-17868)
  * Prevent NullPointerException when changing neverPurgeTombstones from true 
to false (CASSANDRA-17897)
  * Add metrics around storage usage and compression (CASSANDRA-17898)
  * Remove usage of deprecated javax certificate classes (CASSANDRA-17867)
diff --git a/src/java/org/apache/cassandra/config/Config.java 
b/src/java/org/apache/cassandra/config/Config.java
index c3a406b455..168b62a32a 100644
--- a/src/java/org/apache/cassandra/config/Config.java
+++ b/src/java/org/apache/cassandra/config/Config.java
@@ -1052,6 +1052,8 @@ public class Config
      */
     public volatile int paxos_repair_parallelism = -1;
 
+    public volatile boolean sstable_read_rate_persistence_enabled = false;
+
     public volatile int max_top_size_partition_count = 10;
     public volatile int max_top_tombstone_partition_count = 10;
     public volatile DataStorageSpec.LongBytesBound min_tracked_partition_size 
= new DataStorageSpec.LongBytesBound("1MiB");
diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java 
b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
index 482e95fa75..d38bc46b2d 100644
--- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
+++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java
@@ -4496,4 +4496,18 @@ public class DatabaseDescriptor
         else
             logger.info("Setting dump_heap_on_uncaught_exception to {}", 
enabled);
     }
+
+    public static boolean getSStableReadRatePersistenceEnabled()
+    {
+        return conf.sstable_read_rate_persistence_enabled;
+    }
+
+    public static void setSStableReadRatePersistenceEnabled(boolean enabled)
+    {
+        if (enabled != conf.sstable_read_rate_persistence_enabled)
+        {
+            logger.info("Setting sstable_read_rate_persistence_enabled to {}", 
enabled);
+            conf.sstable_read_rate_persistence_enabled = enabled;
+        }
+    }
 }
diff --git a/src/java/org/apache/cassandra/db/SystemKeyspace.java 
b/src/java/org/apache/cassandra/db/SystemKeyspace.java
index 4e11c93d93..533d35ee2c 100644
--- a/src/java/org/apache/cassandra/db/SystemKeyspace.java
+++ b/src/java/org/apache/cassandra/db/SystemKeyspace.java
@@ -81,6 +81,7 @@ import org.apache.cassandra.dht.LocalPartitioner;
 import org.apache.cassandra.dht.Range;
 import org.apache.cassandra.dht.Token;
 import org.apache.cassandra.exceptions.ConfigurationException;
+import org.apache.cassandra.io.sstable.SSTable;
 import org.apache.cassandra.io.sstable.SSTableId;
 import org.apache.cassandra.io.sstable.SequenceBasedSSTableId;
 import org.apache.cassandra.io.util.DataInputBuffer;
@@ -1476,8 +1477,7 @@ public final class SystemKeyspace
      */
     public static RestorableMeter getSSTableReadMeter(String keyspace, String 
table, SSTableId id)
     {
-        String cql = "SELECT * FROM system.%s WHERE keyspace_name=? and 
table_name=? and id=?";
-        UntypedResultSet results = executeInternal(format(cql, 
SSTABLE_ACTIVITY_V2), keyspace, table, id.toString());
+        UntypedResultSet results = readSSTableActivity(keyspace, table, id);
 
         if (results.isEmpty())
             return new RestorableMeter();
@@ -1488,6 +1488,13 @@ public final class SystemKeyspace
         return new RestorableMeter(m15rate, m120rate);
     }
 
+    @VisibleForTesting
+    public static UntypedResultSet readSSTableActivity(String keyspace, String 
table, SSTableId id)
+    {
+        String cql = "SELECT * FROM system.%s WHERE keyspace_name=? and 
table_name=? and id=?";
+        return executeInternal(format(cql, SSTABLE_ACTIVITY_V2), keyspace, 
table, id.toString());
+    }
+
     /**
      * Writes the current read rates for a given SSTable to 
system.sstable_activity
      */
diff --git a/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java 
b/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java
index d7dad42b16..fe8c537b61 100644
--- a/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java
+++ b/src/java/org/apache/cassandra/io/sstable/format/SSTableReader.java
@@ -2160,17 +2160,16 @@ public abstract class SSTableReader extends SSTable 
implements UnfilteredSource,
 
             readMeter = SystemKeyspace.getSSTableReadMeter(desc.ksname, 
desc.cfname, desc.id);
             // sync the average read rate to system.sstable_activity every 
five minutes, starting one minute from now
-            readMeterSyncFuture = new 
WeakReference<>(syncExecutor.scheduleAtFixedRate(new Runnable()
+            readMeterSyncFuture = new 
WeakReference<>(syncExecutor.scheduleAtFixedRate(this::maybePersistSSTableReadMeter,
 1, 5, TimeUnit.MINUTES));
+        }
+
+        void maybePersistSSTableReadMeter()
+        {
+            if (obsoletion == null && 
DatabaseDescriptor.getSStableReadRatePersistenceEnabled())
             {
-                public void run()
-                {
-                    if (obsoletion == null)
-                    {
-                        meterSyncThrottle.acquire();
-                        SystemKeyspace.persistSSTableReadMeter(desc.ksname, 
desc.cfname, desc.id, readMeter);
-                    }
-                }
-            }, 1, 5, TimeUnit.MINUTES));
+                meterSyncThrottle.acquire();
+                SystemKeyspace.persistSSTableReadMeter(desc.ksname, 
desc.cfname, desc.id, readMeter);
+            }
         }
 
         private void stopReadMeterPersistence()
@@ -2389,4 +2388,10 @@ public abstract class SSTableReader extends SSTable 
implements UnfilteredSource,
         }
         return bytes;
     }
+
+    @VisibleForTesting
+    public void maybePersistSSTableReadMeter()
+    {
+        tidy.global.maybePersistSSTableReadMeter();
+    }
 }
diff --git a/src/java/org/apache/cassandra/service/StorageProxy.java 
b/src/java/org/apache/cassandra/service/StorageProxy.java
index 2bf140fc29..4a66b511be 100644
--- a/src/java/org/apache/cassandra/service/StorageProxy.java
+++ b/src/java/org/apache/cassandra/service/StorageProxy.java
@@ -3179,4 +3179,16 @@ public class StorageProxy implements StorageProxyMBean
     {
         DatabaseDescriptor.setDumpHeapOnUncaughtException(enabled);
     }
+
+    @Override
+    public boolean getSStableReadRatePersistenceEnabled()
+    {
+        return DatabaseDescriptor.getSStableReadRatePersistenceEnabled();
+    }
+
+    @Override
+    public void setSStableReadRatePersistenceEnabled(boolean enabled)
+    {
+        DatabaseDescriptor.setSStableReadRatePersistenceEnabled(enabled);
+    }
 }
diff --git a/src/java/org/apache/cassandra/service/StorageProxyMBean.java 
b/src/java/org/apache/cassandra/service/StorageProxyMBean.java
index 5d7bc69569..4a3adfd5bd 100644
--- a/src/java/org/apache/cassandra/service/StorageProxyMBean.java
+++ b/src/java/org/apache/cassandra/service/StorageProxyMBean.java
@@ -138,4 +138,7 @@ public interface StorageProxyMBean
 
     public boolean getDumpHeapOnUncaughtException();
     public void setDumpHeapOnUncaughtException(boolean enabled);
+
+    boolean getSStableReadRatePersistenceEnabled();
+    void setSStableReadRatePersistenceEnabled(boolean enabled);
 }
diff --git a/test/unit/org/apache/cassandra/io/sstable/SSTableReaderTest.java 
b/test/unit/org/apache/cassandra/io/sstable/SSTableReaderTest.java
index f064f19fd9..9567541048 100644
--- a/test/unit/org/apache/cassandra/io/sstable/SSTableReaderTest.java
+++ b/test/unit/org/apache/cassandra/io/sstable/SSTableReaderTest.java
@@ -26,7 +26,7 @@ import java.util.concurrent.*;
 import java.util.stream.Stream;
 
 import com.google.common.collect.Sets;
-import org.apache.cassandra.io.util.File;
+
 import org.junit.BeforeClass;
 import org.junit.Rule;
 import org.junit.Test;
@@ -34,7 +34,9 @@ import org.junit.rules.ExpectedException;
 
 import org.apache.cassandra.SchemaLoader;
 import org.apache.cassandra.Util;
+import org.apache.cassandra.config.DatabaseDescriptor;
 import org.apache.cassandra.cql3.Operator;
+import org.apache.cassandra.cql3.UntypedResultSet;
 import org.apache.cassandra.db.*;
 import org.apache.cassandra.db.compaction.CompactionManager;
 import org.apache.cassandra.db.compaction.OperationType;
@@ -50,6 +52,7 @@ import org.apache.cassandra.dht.Token;
 import org.apache.cassandra.index.Index;
 import org.apache.cassandra.io.FSReadError;
 import org.apache.cassandra.io.sstable.format.SSTableReader;
+import org.apache.cassandra.io.util.File;
 import org.apache.cassandra.io.util.FileDataInput;
 import org.apache.cassandra.io.util.MmappedRegions;
 import org.apache.cassandra.schema.CachingParams;
@@ -59,6 +62,7 @@ import org.apache.cassandra.service.CacheService;
 import org.apache.cassandra.utils.ByteBufferUtil;
 import org.apache.cassandra.utils.FilterFactory;
 
+import static java.lang.String.format;
 import static org.apache.cassandra.cql3.QueryProcessor.executeInternal;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
@@ -178,7 +182,7 @@ public class SSTableReaderTest
                 DecoratedKey dk = Util.dk(String.valueOf(j));
                 FileDataInput file = 
sstable.getFileDataInput(sstable.getPosition(dk, 
SSTableReader.Operator.EQ).position);
                 DecoratedKey keyInDisk = 
sstable.decorateKey(ByteBufferUtil.readWithShortLength(file));
-                assert keyInDisk.equals(dk) : String.format("%s != %s in %s", 
keyInDisk, dk, file.getPath());
+                assert keyInDisk.equals(dk) : format("%s != %s in %s", 
keyInDisk, dk, file.getPath());
             }
 
             // check no false positives
@@ -238,15 +242,41 @@ public class SSTableReaderTest
 
         Util.flush(store);
 
-        SSTableReader sstable = store.getLiveSSTables().iterator().next();
-        assertEquals(0, sstable.getReadMeter().count());
+        boolean startState = 
DatabaseDescriptor.getSStableReadRatePersistenceEnabled();
+        try
+        {
+            DatabaseDescriptor.setSStableReadRatePersistenceEnabled(true);
+
+            SSTableReader sstable = store.getLiveSSTables().iterator().next();
+            assertEquals(0, sstable.getReadMeter().count());
 
-        DecoratedKey key = sstable.decorateKey(ByteBufferUtil.bytes("4"));
-        Util.getAll(Util.cmd(store, key).build());
-        assertEquals(1, sstable.getReadMeter().count());
+            DecoratedKey key = sstable.decorateKey(ByteBufferUtil.bytes("4"));
+            Util.getAll(Util.cmd(store, key).build());
+            assertEquals(1, sstable.getReadMeter().count());
 
-        Util.getAll(Util.cmd(store, key).includeRow("0").build());
-        assertEquals(2, sstable.getReadMeter().count());
+            Util.getAll(Util.cmd(store, key).includeRow("0").build());
+            assertEquals(2, sstable.getReadMeter().count());
+
+            // With persistence enabled, we should be able to retrieve the 
state of the meter.
+            sstable.maybePersistSSTableReadMeter();
+
+            UntypedResultSet meter = 
SystemKeyspace.readSSTableActivity(store.keyspace.getName(), store.name, 
sstable.descriptor.id);
+            assertFalse(meter.isEmpty());
+
+            Util.getAll(Util.cmd(store, key).includeRow("0").build());
+            assertEquals(3, sstable.getReadMeter().count());
+
+            // After cleaning existing state and disabling persistence, there 
should be no meter state to read.
+            SystemKeyspace.clearSSTableReadMeter(store.keyspace.getName(), 
store.name, sstable.descriptor.id);
+            DatabaseDescriptor.setSStableReadRatePersistenceEnabled(false);
+            sstable.maybePersistSSTableReadMeter();
+            meter = 
SystemKeyspace.readSSTableActivity(store.keyspace.getName(), store.name, 
sstable.descriptor.id);
+            assertTrue(meter.isEmpty());
+        }
+        finally
+        {
+            
DatabaseDescriptor.setSStableReadRatePersistenceEnabled(startState);
+        }
     }
 
     @Test
@@ -432,7 +462,7 @@ public class SSTableReaderTest
         assert target.first.equals(firstKey);
         assert target.last.equals(lastKey);
 
-        executeInternal(String.format("ALTER TABLE \"%s\".\"%s\" WITH 
bloom_filter_fp_chance = 0.3", ks, cf));
+        executeInternal(format("ALTER TABLE \"%s\".\"%s\" WITH 
bloom_filter_fp_chance = 0.3", ks, cf));
 
         File summaryFile = new File(desc.filenameFor(Component.SUMMARY));
         Path bloomPath = new File(desc.filenameFor(Component.FILTER)).toPath();
@@ -613,9 +643,9 @@ public class SSTableReaderTest
         final int NUM_PARTITIONS = 512;
         for (int j = 0; j < NUM_PARTITIONS; j++)
         {
-            new RowUpdateBuilder(store.metadata(), j, String.format("%3d", j))
+            new RowUpdateBuilder(store.metadata(), j, format("%3d", j))
             .clustering("0")
-            .add("val", String.format("%3d", j))
+            .add("val", format("%3d", j))
             .build()
             .applyUnsafe();
 
@@ -631,7 +661,7 @@ public class SSTableReaderTest
         List<Future<?>> futures = new ArrayList<>(NUM_PARTITIONS * 2);
         for (int i = 0; i < NUM_PARTITIONS; i++)
         {
-            final ByteBuffer key = ByteBufferUtil.bytes(String.format("%3d", 
i));
+            final ByteBuffer key = ByteBufferUtil.bytes(format("%3d", i));
             final int index = i;
 
             futures.add(executor.submit(new Runnable()
@@ -639,7 +669,7 @@ public class SSTableReaderTest
                 public void run()
                 {
                     Row row = Util.getOnlyRowUnfiltered(Util.cmd(store, 
key).build());
-                    assertEquals(0, 
ByteBufferUtil.compare(String.format("%3d", index).getBytes(), 
row.cells().iterator().next().buffer()));
+                    assertEquals(0, ByteBufferUtil.compare(format("%3d", 
index).getBytes(), row.cells().iterator().next().buffer()));
                 }
             }));
 
@@ -690,9 +720,9 @@ public class SSTableReaderTest
         final int NUM_PARTITIONS = 512;
         for (int j = 0; j < NUM_PARTITIONS; j++)
         {
-            new RowUpdateBuilder(store.metadata(), j, String.format("%3d", j))
+            new RowUpdateBuilder(store.metadata(), j, format("%3d", j))
             .clustering("0")
-            .add("val", String.format("%3d", j))
+            .add("val", format("%3d", j))
             .build()
             .applyUnsafe();
 
@@ -791,7 +821,7 @@ public class SSTableReaderTest
         {
             File f = new File(notLiveDesc.filenameFor(c));
             assertTrue(f.exists());
-            assertTrue(f.toString().contains(String.format("-%s-", id)));
+            assertTrue(f.toString().contains(format("-%s-", id)));
             f.deleteOnExit();
             assertFalse(new File(sstable.descriptor.filenameFor(c)).exists());
         }


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

Reply via email to