From 4e410fc46da5d6759463230ab09a718178dbd4d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20de=20la=20Pe=C3=B1a?= Date: Wed, 27 Jul 2022 12:50:31 +0100 Subject: [PATCH] Document usage of closed token intervals in manual compaction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit patch by Andrés de la Peña; reviewed by Ekaterina Dimitrova for CASSANDRA-17575 --- CHANGES.txt | 1 + .../cassandra/db/ColumnFamilyStoreMBean.java | 7 +++- .../db/compaction/CompactionManager.java | 15 +++++++++ .../service/StorageServiceMBean.java | 8 ++++- .../org/apache/cassandra/tools/NodeProbe.java | 8 +++++ .../cassandra/tools/nodetool/Compact.java | 4 +-- .../LeveledCompactionStrategyTest.java | 33 ++++++++++--------- 7 files changed, 57 insertions(+), 19 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 7297b3d8f9..9abbbf54aa 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.11.14 + * Document usage of closed token intervals in manual compaction (CASSANDRA-17575) * Creating of a keyspace on insufficient number of replicas should filter out gosspping-only members (CASSANDRA-17759) * Only use statically defined subcolumns when determining column definition for supercolumn cell (CASSANDRA-14113) Merged from 3.0: diff --git a/src/java/org/apache/cassandra/db/ColumnFamilyStoreMBean.java b/src/java/org/apache/cassandra/db/ColumnFamilyStoreMBean.java index e7b191743e..07201c5ab5 100644 --- a/src/java/org/apache/cassandra/db/ColumnFamilyStoreMBean.java +++ b/src/java/org/apache/cassandra/db/ColumnFamilyStoreMBean.java @@ -49,7 +49,12 @@ public interface ColumnFamilyStoreMBean public void forceMajorCompaction(boolean splitOutput) throws ExecutionException, InterruptedException; /** - * force a major compaction of specified key range in this column family + * Forces a major compaction of specified token ranges in this column family. + *

+ * The token ranges will be interpreted as closed intervals to match the closed interval defined by the first and + * last keys of a sstable, even though the {@link Range} class is suppossed to be half-open by definition. + * + * @param tokenRanges The token ranges to be compacted, interpreted as closed intervals. */ public void forceCompactionForTokenRange(Collection> tokenRanges) throws ExecutionException, InterruptedException; /** diff --git a/src/java/org/apache/cassandra/db/compaction/CompactionManager.java b/src/java/org/apache/cassandra/db/compaction/CompactionManager.java index 76f6a98833..82e0bf2f5e 100644 --- a/src/java/org/apache/cassandra/db/compaction/CompactionManager.java +++ b/src/java/org/apache/cassandra/db/compaction/CompactionManager.java @@ -812,6 +812,15 @@ public class CompactionManager implements CompactionManagerMBean return futures; } + /** + * Forces a major compaction of specified token ranges of the specified column family. + *

+ * The token ranges will be interpreted as closed intervals to match the closed interval defined by the first and + * last keys of a sstable, even though the {@link Range} class is suppossed to be half-open by definition. + * + * @param cfStore The column family store to be compacted. + * @param ranges The token ranges to be compacted, interpreted as closed intervals. + */ public void forceCompactionForTokenRange(ColumnFamilyStore cfStore, Collection> ranges) { Callable> taskCreator = () -> { @@ -849,6 +858,12 @@ public class CompactionManager implements CompactionManagerMBean FBUtilities.waitOnFuture(executor.submitIfRunning(runnable, "force compaction for token range")); } + /** + * Returns the sstables of the specified column family store that intersect with the specified token ranges. + *

+ * The token ranges will be interpreted as closed intervals to match the closed interval defined by the first and + * last keys of a sstable, even though the {@link Range} class is suppossed to be half-open by definition. + */ private static Collection sstablesInBounds(ColumnFamilyStore cfs, Collection> tokenRangeCollection) { final Set sstables = new HashSet<>(); diff --git a/src/java/org/apache/cassandra/service/StorageServiceMBean.java b/src/java/org/apache/cassandra/service/StorageServiceMBean.java index 233673ad30..f456d4eb59 100644 --- a/src/java/org/apache/cassandra/service/StorageServiceMBean.java +++ b/src/java/org/apache/cassandra/service/StorageServiceMBean.java @@ -265,8 +265,14 @@ public interface StorageServiceMBean extends NotificationEmitter @Deprecated public int relocateSSTables(String keyspace, String ... cfnames) throws IOException, ExecutionException, InterruptedException; public int relocateSSTables(int jobs, String keyspace, String ... cfnames) throws IOException, ExecutionException, InterruptedException; + /** - * Forces major compaction of specified token range in a single keyspace + * Forces major compaction of specified token range in a single keyspace. + * + * @param keyspaceName the name of the keyspace to be compacted + * @param startToken the token at which the compaction range starts (inclusive) + * @param endToken the token at which compaction range ends (inclusive) + * @param tableNames the names of the tables to be compacted */ public void forceKeyspaceCompactionForTokenRange(String keyspaceName, String startToken, String endToken, String... tableNames) throws IOException, ExecutionException, InterruptedException; diff --git a/src/java/org/apache/cassandra/tools/NodeProbe.java b/src/java/org/apache/cassandra/tools/NodeProbe.java index c63f2a1d87..821b8a3bd6 100644 --- a/src/java/org/apache/cassandra/tools/NodeProbe.java +++ b/src/java/org/apache/cassandra/tools/NodeProbe.java @@ -397,6 +397,14 @@ public class NodeProbe implements AutoCloseable ssProxy.relocateSSTables(jobs, keyspace, cfnames); } + /** + * Forces major compaction of specified token range in a single keyspace. + * + * @param keyspaceName the name of the keyspace to be compacted + * @param startToken the token at which the compaction range starts (inclusive) + * @param endToken the token at which compaction range ends (inclusive) + * @param tableNames the names of the tables to be compacted + */ public void forceKeyspaceCompactionForTokenRange(String keyspaceName, final String startToken, final String endToken, String... tableNames) throws IOException, ExecutionException, InterruptedException { ssProxy.forceKeyspaceCompactionForTokenRange(keyspaceName, startToken, endToken, tableNames); diff --git a/src/java/org/apache/cassandra/tools/nodetool/Compact.java b/src/java/org/apache/cassandra/tools/nodetool/Compact.java index ef10a836b2..d4731902a6 100644 --- a/src/java/org/apache/cassandra/tools/nodetool/Compact.java +++ b/src/java/org/apache/cassandra/tools/nodetool/Compact.java @@ -41,10 +41,10 @@ public class Compact extends NodeToolCmd @Option(title = "user-defined", name = {"--user-defined"}, description = "Use --user-defined to submit listed files for user-defined compaction") private boolean userDefined = false; - @Option(title = "start_token", name = {"-st", "--start-token"}, description = "Use -st to specify a token at which the compaction range starts") + @Option(title = "start_token", name = {"-st", "--start-token"}, description = "Use -st to specify a token at which the compaction range starts (inclusive)") private String startToken = EMPTY; - @Option(title = "end_token", name = {"-et", "--end-token"}, description = "Use -et to specify a token at which compaction range ends") + @Option(title = "end_token", name = {"-et", "--end-token"}, description = "Use -et to specify a token at which compaction range ends (inclusive)") private String endToken = EMPTY; diff --git a/test/unit/org/apache/cassandra/db/compaction/LeveledCompactionStrategyTest.java b/test/unit/org/apache/cassandra/db/compaction/LeveledCompactionStrategyTest.java index 91b9b3b7d3..9b59e73a2c 100644 --- a/test/unit/org/apache/cassandra/db/compaction/LeveledCompactionStrategyTest.java +++ b/test/unit/org/apache/cassandra/db/compaction/LeveledCompactionStrategyTest.java @@ -385,12 +385,10 @@ public class LeveledCompactionStrategyTest assertFalse(repaired.manifest.getLevel(1).contains(sstable2)); } - - @Test public void testTokenRangeCompaction() throws Exception { - // Remove any existing data so we can start out clean with predictable number of sstables + // Remove any existing data, so we can start out clean with predictable number of sstables cfs.truncateBlocking(); // Disable auto compaction so cassandra does not compact @@ -400,15 +398,17 @@ public class LeveledCompactionStrategyTest DecoratedKey key1 = Util.dk(String.valueOf(1)); DecoratedKey key2 = Util.dk(String.valueOf(2)); - List keys = new ArrayList<>(Arrays.asList(key1, key2)); + List keys = Arrays.asList(key1, key2); int numIterations = 10; int columns = 2; // Add enough data to trigger multiple sstables. // create 10 sstables that contain data for both key1 and key2 - for (int i = 0; i < numIterations; i++) { - for (DecoratedKey key : keys) { + for (int i = 0; i < numIterations; i++) + { + for (DecoratedKey key : keys) + { UpdateBuilder update = UpdateBuilder.create(cfs.metadata, key); for (int c = 0; c < columns; c++) update.newRow("column" + c).add("val", value); @@ -418,8 +418,10 @@ public class LeveledCompactionStrategyTest } // create 20 more sstables with 10 containing data for key1 and other 10 containing data for key2 - for (int i = 0; i < numIterations; i++) { - for (DecoratedKey key : keys) { + for (int i = 0; i < numIterations; i++) + { + for (DecoratedKey key : keys) + { UpdateBuilder update = UpdateBuilder.create(cfs.metadata, key); for (int c = 0; c < columns; c++) update.newRow("column" + c).add("val", value); @@ -431,13 +433,14 @@ public class LeveledCompactionStrategyTest // We should have a total of 30 sstables by now assertEquals(30, cfs.getLiveSSTables().size()); - // Compact just the tables with key2 - // Bit hackish to use the key1.token as the prior key but works in BytesToken + // Compact just the tables with key2. The token ranges for compaction are interpreted as closed intervals, + // so we can use [token, token] to select a single token. Range tokenRange = new Range<>(key2.getToken(), key2.getToken()); - Collection> tokenRanges = new ArrayList<>(Arrays.asList(tokenRange)); + Collection> tokenRanges = singleton(tokenRange); cfs.forceCompactionForTokenRange(tokenRanges); - while(CompactionManager.instance.isCompacting(Arrays.asList(cfs))) { + while (CompactionManager.instance.isCompacting(singleton(cfs))) + { Thread.sleep(100); } @@ -446,11 +449,11 @@ public class LeveledCompactionStrategyTest // Compact just the tables with key1. At this point all 11 tables should have key1 Range tokenRange2 = new Range<>(key1.getToken(), key1.getToken()); - Collection> tokenRanges2 = new ArrayList<>(Arrays.asList(tokenRange2)); + Collection> tokenRanges2 = new ArrayList<>(singleton(tokenRange2)); cfs.forceCompactionForTokenRange(tokenRanges2); - - while(CompactionManager.instance.isCompacting(Arrays.asList(cfs))) { + while (CompactionManager.instance.isCompacting(singleton(cfs))) + { Thread.sleep(100); }