diff --git a/CHANGES.txt b/CHANGES.txt index 4d2ef6c3d4..c4fde4445e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -106,6 +106,7 @@ * Add the ability to disable bulk loading of SSTables (CASSANDRA-18781) * Clean up obsolete functions and simplify cql_version handling in cqlsh (CASSANDRA-18787) Merged from 5.0: + * Add flag to avoid invalidating key cache on sstable deletions (CASSANDRA-20068) * Interpret inet, bigint, varint, and decimal as non-reversed types for query construction and post-filtering (CASSANDRA-20100) * Streamline the serialized format for index status gossip messages (CASSANDRA-20058) * Batch clusterings into single SAI partition post-filtering reads (CASSANDRA-19497) diff --git a/src/java/org/apache/cassandra/config/Config.java b/src/java/org/apache/cassandra/config/Config.java index ca4cf09be4..9335953d20 100644 --- a/src/java/org/apache/cassandra/config/Config.java +++ b/src/java/org/apache/cassandra/config/Config.java @@ -464,6 +464,7 @@ public class Config public volatile DataStorageSpec.IntMebibytesBound sstable_preemptive_open_interval = new DataStorageSpec.IntMebibytesBound("50MiB"); public volatile boolean key_cache_migrate_during_compaction = true; + public volatile boolean key_cache_invalidate_after_sstable_deletion = false; public volatile int key_cache_keys_to_save = Integer.MAX_VALUE; @Replaces(oldName = "key_cache_size_in_mb", converter = Converters.MEBIBYTES_DATA_STORAGE_LONG, deprecated = true) public DataStorageSpec.LongMebibytesBound key_cache_size = null; diff --git a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java index 3cd003b97b..f80dcfd5b5 100644 --- a/src/java/org/apache/cassandra/config/DatabaseDescriptor.java +++ b/src/java/org/apache/cassandra/config/DatabaseDescriptor.java @@ -3841,6 +3841,16 @@ public class DatabaseDescriptor conf.key_cache_migrate_during_compaction = migrateCacheEntry; } + public static boolean shouldInvalidateKeycacheOnSSTableDeletion() + { + return conf.key_cache_invalidate_after_sstable_deletion; + } + + public static void setInvalidateKeycacheOnSSTableDeletion(boolean invalidateCacheEntry) + { + conf.key_cache_invalidate_after_sstable_deletion = invalidateCacheEntry; + } + /** * This method can return negative number for disabled */ diff --git a/src/java/org/apache/cassandra/io/sstable/format/big/BigFormat.java b/src/java/org/apache/cassandra/io/sstable/format/big/BigFormat.java index 585e6c389c..795678841a 100644 --- a/src/java/org/apache/cassandra/io/sstable/format/big/BigFormat.java +++ b/src/java/org/apache/cassandra/io/sstable/format/big/BigFormat.java @@ -340,13 +340,16 @@ public class BigFormat extends AbstractSSTableFormat it = CacheService.instance.keyCache.keyIterator(); - while (it.hasNext()) + if (DatabaseDescriptor.shouldInvalidateKeycacheOnSSTableDeletion()) { - KeyCacheKey key = it.next(); - if (key.desc.equals(desc)) - it.remove(); + // remove key cache entries for the sstable being deleted + Iterator it = CacheService.instance.keyCache.keyIterator(); + while (it.hasNext()) + { + KeyCacheKey key = it.next(); + if (key.desc.equals(desc)) + it.remove(); + } } delete(desc, Lists.newArrayList(Sets.intersection(allComponents(), desc.discoverComponents()))); diff --git a/src/java/org/apache/cassandra/service/StorageService.java b/src/java/org/apache/cassandra/service/StorageService.java index 9c20aa262d..47bb83a5ec 100644 --- a/src/java/org/apache/cassandra/service/StorageService.java +++ b/src/java/org/apache/cassandra/service/StorageService.java @@ -4502,6 +4502,16 @@ public class StorageService extends NotificationBroadcasterSupport implements IE DatabaseDescriptor.setMigrateKeycacheOnCompaction(invalidateKeyCacheOnCompaction); } + public boolean getInvalidateKeycacheOnSSTableDeletion() + { + return DatabaseDescriptor.shouldInvalidateKeycacheOnSSTableDeletion(); + } + + public void setInvalidateKeycacheOnSSTableDeletion(boolean invalidate) + { + DatabaseDescriptor.setInvalidateKeycacheOnSSTableDeletion(invalidate); + } + public int getTombstoneWarnThreshold() { return DatabaseDescriptor.getTombstoneWarnThreshold(); diff --git a/src/java/org/apache/cassandra/service/StorageServiceMBean.java b/src/java/org/apache/cassandra/service/StorageServiceMBean.java index 2a9096762a..1529a59a56 100644 --- a/src/java/org/apache/cassandra/service/StorageServiceMBean.java +++ b/src/java/org/apache/cassandra/service/StorageServiceMBean.java @@ -850,6 +850,8 @@ public interface StorageServiceMBean extends NotificationEmitter public boolean getMigrateKeycacheOnCompaction(); public void setMigrateKeycacheOnCompaction(boolean invalidateKeyCacheOnCompaction); + public boolean getInvalidateKeycacheOnSSTableDeletion(); + public void setInvalidateKeycacheOnSSTableDeletion(boolean invalidate); public int getConcurrentViewBuilders(); public void setConcurrentViewBuilders(int value); diff --git a/test/unit/org/apache/cassandra/io/sstable/keycache/KeyCacheTest.java b/test/unit/org/apache/cassandra/io/sstable/keycache/KeyCacheTest.java index 15c37ea60a..abe83b59d5 100644 --- a/test/unit/org/apache/cassandra/io/sstable/keycache/KeyCacheTest.java +++ b/test/unit/org/apache/cassandra/io/sstable/keycache/KeyCacheTest.java @@ -350,14 +350,14 @@ public class KeyCacheTest LifecycleTransaction.waitForDeletions(); - // after releasing the reference this should drop to 2 - assertKeyCacheSize(2, KEYSPACE1, cf); + // after releasing the reference this should drop to 2, unless we don't invalidate keycache on sstable deletion + assertKeyCacheSize(DatabaseDescriptor.shouldInvalidateKeycacheOnSSTableDeletion() ? 2 : 4, KEYSPACE1, cf); // re-read same keys to verify that key cache didn't grow further Util.getAll(Util.cmd(cfs, "key1").build()); Util.getAll(Util.cmd(cfs, "key2").build()); - assertKeyCacheSize( 2, KEYSPACE1, cf); + assertKeyCacheSize( DatabaseDescriptor.shouldInvalidateKeycacheOnSSTableDeletion() ? 2 : 4, KEYSPACE1, cf); } @Test