This is an automated email from the ASF dual-hosted git repository.
ycai 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 d6f1810 Add an option to nodetool tablestats to check sstable
location correctness
d6f1810 is described below
commit d6f18106f09e7b1a58744c9bd1ee35054a43d68a
Author: Yifan Cai <[email protected]>
AuthorDate: Thu Feb 11 21:53:47 2021 -0800
Add an option to nodetool tablestats to check sstable location correctness
patch by Yifan Cai; reviewed by Ekaterina Dimitrova, Marcus Eriksson for
CASSANDRA-16344
---
CHANGES.txt | 1 +
.../org/apache/cassandra/db/ColumnFamilyStore.java | 21 +++
.../cassandra/db/ColumnFamilyStoreMBean.java | 7 +
.../org/apache/cassandra/db/DiskBoundaries.java | 7 +
.../cassandra/db/compaction/CompactionManager.java | 12 +-
.../cassandra/tools/nodetool/TableStats.java | 7 +-
.../cassandra/tools/nodetool/stats/StatsTable.java | 1 +
.../tools/nodetool/stats/TableStatsHolder.java | 11 +-
.../tools/nodetool/stats/TableStatsPrinter.java | 2 +
.../test/MultipleDataDirectoryTest.java | 172 +++++++++++++++++++++
.../nodetool/stats/NodetoolTableStatsTest.java | 58 +++++--
.../nodetool/stats/TableStatsPrinterTest.java | 2 +-
12 files changed, 273 insertions(+), 28 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 9f6ee1b..7b6a9f1 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
4.0-beta5
+ * Add an option to nodetool tablestats to check sstable location correctness
(CASSANDRA-16344)
* Unable to ALTER KEYSPACE while decommissioned/assassinated nodes are in
gossip (CASSANDRA-16422)
* Metrics backward compatibility restored after CASSANDRA-15066
(CASSANDRA-16083)
* Reduce new reserved keywords introduced since 3.0 (CASSANDRA-16439)
diff --git a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
index 64ea6a6..1089e13 100644
--- a/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
+++ b/src/java/org/apache/cassandra/db/ColumnFamilyStore.java
@@ -2880,4 +2880,25 @@ public class ColumnFamilyStore implements
ColumnFamilyStoreMBean
Collections.addAll(collection, localSystemDiskFlushExecutors);
}
}
+
+ /*
+ * Check SSTables whether or not they are misplaced.
+ * @return true if any of the SSTables is misplaced.
+ * If all SSTables are correctly placed or the partitioner does
not support splitting, it returns false.
+ */
+ @Override
+ public boolean hasMisplacedSSTables()
+ {
+ if (!getPartitioner().splitter().isPresent())
+ return false;
+
+ final DiskBoundaries diskBoundaries = getDiskBoundaries();
+ for (SSTableReader sstable : getSSTables(SSTableSet.CANONICAL))
+ {
+ Directories.DataDirectory dataDirectory =
getDirectories().getDataDirectoryForFile(sstable.descriptor);
+ if (!diskBoundaries.isInCorrectLocation(sstable, dataDirectory))
+ return true;
+ }
+ return false;
+ }
}
diff --git a/src/java/org/apache/cassandra/db/ColumnFamilyStoreMBean.java
b/src/java/org/apache/cassandra/db/ColumnFamilyStoreMBean.java
index fb0d611..c2cf393 100644
--- a/src/java/org/apache/cassandra/db/ColumnFamilyStoreMBean.java
+++ b/src/java/org/apache/cassandra/db/ColumnFamilyStoreMBean.java
@@ -218,4 +218,11 @@ public interface ColumnFamilyStoreMBean
public void setNeverPurgeTombstones(boolean value);
public boolean getNeverPurgeTombstones();
+
+ /**
+ * Check SSTables whether or not they are misplaced.
+ * @return true if any of the SSTables is misplaced.
+ * If all SSTables are correctly placed or the partitioner does
not support splitting, it returns false.
+ */
+ public boolean hasMisplacedSSTables();
}
diff --git a/src/java/org/apache/cassandra/db/DiskBoundaries.java
b/src/java/org/apache/cassandra/db/DiskBoundaries.java
index 5b377e2..f33b43e 100644
--- a/src/java/org/apache/cassandra/db/DiskBoundaries.java
+++ b/src/java/org/apache/cassandra/db/DiskBoundaries.java
@@ -141,6 +141,13 @@ public class DiskBoundaries
return directories.get(getDiskIndex(key));
}
+ public boolean isInCorrectLocation(SSTableReader sstable,
Directories.DataDirectory currentLocation)
+ {
+ int diskIndex = getDiskIndex(sstable);
+ PartitionPosition diskLast = positions.get(diskIndex);
+ return directories.get(diskIndex).equals(currentLocation) &&
sstable.last.compareTo(diskLast) <= 0;
+ }
+
private int getDiskIndex(DecoratedKey key)
{
int pos = Collections.binarySearch(positions, key);
diff --git a/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
b/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
index 7df56fc..acb21b2 100644
--- a/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
+++ b/src/java/org/apache/cassandra/db/compaction/CompactionManager.java
@@ -660,13 +660,9 @@ public class CompactionManager implements
CompactionManagerMBean
if (!cfs.getPartitioner().splitter().isPresent())
return true;
- int diskIndex = diskBoundaries.getDiskIndex(sstable);
- PartitionPosition diskLast =
diskBoundaries.positions.get(diskIndex);
-
- // the location we get from directoryIndex is based on the
first key in the sstable
- // now we need to make sure the last key is less than the
boundary as well:
- Directories.DataDirectory dataDirectory =
cfs.getDirectories().getDataDirectoryForFile(sstable.descriptor);
- return
diskBoundaries.directories.get(diskIndex).equals(dataDirectory) &&
sstable.last.compareTo(diskLast) <= 0;
+ // Compare the expected data directory for the sstable with
its current data directory
+ Directories.DataDirectory currentDirectory =
cfs.getDirectories().getDataDirectoryForFile(sstable.descriptor);
+ return diskBoundaries.isInCorrectLocation(sstable,
currentDirectory);
}
@Override
@@ -1476,7 +1472,7 @@ public class CompactionManager implements
CompactionManagerMBean
* @param txn a transaction over the repaired sstables to anticompact
* @param ranges full and transient ranges to be placed into one of the
new sstables. The repaired table will be tracked via
* the {@link
org.apache.cassandra.io.sstable.metadata.StatsMetadata#pendingRepair} field.
- * @param sessionID the repair session we're anti-compacting for
+ * @param pendingRepair the repair session we're anti-compacting for
* @param isCancelled function that indicates if active anti-compaction
should be canceled
*/
private void doAntiCompaction(ColumnFamilyStore cfs,
diff --git a/src/java/org/apache/cassandra/tools/nodetool/TableStats.java
b/src/java/org/apache/cassandra/tools/nodetool/TableStats.java
index 47ca132..4a33c64 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/TableStats.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/TableStats.java
@@ -68,6 +68,11 @@ public class TableStats extends NodeToolCmd
description = "Show only the top K tables for the sort key
(specify the number K of tables to be shown")
private int top = 0;
+ @Option(title = "sstable_location_check",
+ name = {"-l", "--sstable-location-check"},
+ description = "Check whether or not the SSTables are in the
correct location.")
+ private boolean locationCheck = false;
+
@Override
public void execute(NodeProbe probe)
{
@@ -92,7 +97,7 @@ public class TableStats extends NodeToolCmd
throw new IllegalArgumentException("argument for top must be a
positive integer.");
}
- StatsHolder holder = new TableStatsHolder(probe, humanReadable,
ignore, tableNames, sortKey, top);
+ StatsHolder holder = new TableStatsHolder(probe, humanReadable,
ignore, tableNames, sortKey, top, locationCheck);
// print out the keyspace and table statistics
StatsPrinter printer = TableStatsPrinter.from(outputFormat,
!sortKey.isEmpty());
printer.print(holder, probe.output().out);
diff --git a/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTable.java
b/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTable.java
index 01d2164..d897eab 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTable.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/stats/StatsTable.java
@@ -69,4 +69,5 @@ public class StatsTable
public long maximumTombstonesPerSliceLastFiveMinutes;
public String droppedMutations;
public List<String> sstablesInEachLevel = new ArrayList<>();
+ public Boolean isInCorrectLocation = null; // null: option not active
}
diff --git
a/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsHolder.java
b/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsHolder.java
index 624484f..8b9b722 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsHolder.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsHolder.java
@@ -35,13 +35,16 @@ public class TableStatsHolder implements StatsHolder
public final boolean humanReadable;
public final String sortKey;
public final int top;
+ public final boolean locationCheck;
- public TableStatsHolder(NodeProbe probe, boolean humanReadable, boolean
ignore, List<String> tableNames, String sortKey, int top)
+ public TableStatsHolder(NodeProbe probe, boolean humanReadable, boolean
ignore, List<String> tableNames, String sortKey, int top, boolean locationCheck)
{
this.keyspaces = new ArrayList<>();
this.humanReadable = humanReadable;
this.sortKey = sortKey;
this.top = top;
+ this.locationCheck = locationCheck;
+
if (!this.isTestTableStatsHolder())
{
this.numberOfTables = probe.getNumberOfTables();
@@ -155,6 +158,8 @@ public class TableStatsHolder implements StatsHolder
mpTable.put("maximum_tombstones_per_slice_last_five_minutes",
table.maximumTombstonesPerSliceLastFiveMinutes);
mpTable.put("dropped_mutations", table.droppedMutations);
+ if (locationCheck)
+ mpTable.put("sstables_in_correct_location",
table.isInCorrectLocation);
return mpTable;
}
@@ -210,6 +215,7 @@ public class TableStatsHolder implements StatsHolder
statsTable.isIndex = tableName.contains(".");
statsTable.sstableCount =
probe.getColumnFamilyMetric(keyspaceName, tableName, "LiveSSTableCount");
statsTable.oldSSTableCount =
probe.getColumnFamilyMetric(keyspaceName, tableName, "OldVersionSSTableCount");
+
int[] leveledSStables = table.getSSTableCountPerLevel();
if (leveledSStables != null)
{
@@ -226,6 +232,9 @@ public class TableStatsHolder implements StatsHolder
}
}
+ if (locationCheck)
+ statsTable.isInCorrectLocation =
!table.hasMisplacedSSTables();
+
Long memtableOffHeapSize = null;
Long bloomFilterOffHeapSize = null;
Long indexSummaryOffHeapSize = null;
diff --git
a/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinter.java
b/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinter.java
index 2291f45..8c27e1e 100644
--- a/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinter.java
+++ b/src/java/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinter.java
@@ -120,6 +120,8 @@ public class TableStatsPrinter<T extends StatsHolder>
out.println(indent + "Average tombstones per slice (last five
minutes): " + table.averageTombstonesPerSliceLastFiveMinutes);
out.println(indent + "Maximum tombstones per slice (last five
minutes): " + table.maximumTombstonesPerSliceLastFiveMinutes);
out.println(indent + "Dropped Mutations: " +
table.droppedMutations);
+ if (table.isInCorrectLocation != null)
+ out.println(indent + "SSTables in correct location: " +
table.isInCorrectLocation);
out.println("");
}
}
diff --git
a/test/distributed/org/apache/cassandra/distributed/test/MultipleDataDirectoryTest.java
b/test/distributed/org/apache/cassandra/distributed/test/MultipleDataDirectoryTest.java
new file mode 100644
index 0000000..a2f4aab
--- /dev/null
+++
b/test/distributed/org/apache/cassandra/distributed/test/MultipleDataDirectoryTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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.distributed.test;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.util.Iterator;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import org.apache.cassandra.config.DatabaseDescriptor;
+import org.apache.cassandra.db.ColumnFamilyStore;
+import org.apache.cassandra.db.Keyspace;
+import org.apache.cassandra.distributed.Cluster;
+import org.apache.cassandra.distributed.api.IInvokableInstance;
+import org.apache.cassandra.io.sstable.Component;
+import org.apache.cassandra.io.sstable.Descriptor;
+import org.apache.cassandra.io.sstable.format.SSTableReader;
+
+public class MultipleDataDirectoryTest extends TestBaseImpl
+{
+ private static Cluster CLUSTER;
+ private static IInvokableInstance NODE;
+
+ @BeforeClass
+ public static void before() throws IOException
+ {
+ CLUSTER =
init(Cluster.build().withNodes(1).withDataDirCount(3).start());
+ NODE = CLUSTER.get(1);
+ CLUSTER.schemaChange(withKeyspace("CREATE TABLE %s.cf (k text, c1
text, c2 text, PRIMARY KEY (k)) WITH compaction = {'class':
'LeveledCompactionStrategy', 'enabled': 'false'}"));
+ Assert.assertEquals(3, NODE.callsOnInstance(() ->
DatabaseDescriptor.getAllDataFileLocations().length).call().intValue());
+ }
+
+ @AfterClass
+ public static void after()
+ {
+ if (CLUSTER != null)
+ CLUSTER.close();
+ }
+
+ @Before
+ public void populateData()
+ {
+ final int rowsPerFile = 500;
+ final int files = 5;
+ for (int k = 0; k < files; k++)
+ {
+ for (int i = k * rowsPerFile; i < k * rowsPerFile + rowsPerFile;
++i)
+ NODE.executeInternal(withKeyspace("INSERT INTO %s.cf (k, c1,
c2) VALUES (?, 'value1', 'value2');"), Integer.toString(i));
+ NODE.nodetool("flush");
+ }
+ }
+
+ @After
+ public void cleanupData()
+ {
+ NODE.runOnInstance(() -> {
+
Keyspace.open(KEYSPACE).getColumnFamilyStore("cf").truncateBlocking();
+ });
+ }
+
+ @Test
+ public void testSSTablesAreInCorrectLocation()
+ {
+ NODE.runOnInstance(() -> {
+ ColumnFamilyStore cfs =
Keyspace.open(KEYSPACE).getColumnFamilyStore("cf");
+ Assert.assertFalse("All SSTables should be in the correct
location",
+ cfs.hasMisplacedSSTables());
+ });
+ }
+
+ @Test
+ public void testDetectSSTableMisplaced()
+ {
+ setupMisplacedSSTables();
+ NODE.runOnInstance(() -> {
+ ColumnFamilyStore cfs =
Keyspace.open(KEYSPACE).getColumnFamilyStore("cf");
+ Assert.assertTrue("Some SSTable should be misplaced",
+ cfs.hasMisplacedSSTables());
+ });
+ }
+
+ @Test
+ public void testNodeToolRelocateSSTablesFindNoFilesToMove()
+ {
+ long logStartLoc = NODE.logs().mark();
+ NODE.nodetoolResult("relocatesstables", KEYSPACE, "cf")
+ .asserts()
+ .success();
+ String expectedLog = String.format("No sstables to RELOCATE for
%s.%s", KEYSPACE, "cf");
+ Assert.assertEquals("relocatesstables should find no sstables to move",
+ 1, NODE.logs().grep(logStartLoc,
expectedLog).getResult().size());
+ }
+
+ @Test
+ public void testNodeToolRelocateSSTables()
+ {
+ setupMisplacedSSTables();
+ long logStartLoc = NODE.logs().mark();
+ NODE.nodetoolResult("relocatesstables", KEYSPACE, "cf")
+ .asserts()
+ .success();
+ String expectedLog = String.format("Finished Relocate sstables to
correct disk for %s.%s successfully", KEYSPACE, "cf");
+ Assert.assertEquals("relocatesstables should find sstables to move",
+ 1, NODE.logs().grep(logStartLoc,
expectedLog).getResult().size());
+ NODE.runOnInstance(() -> {
+ ColumnFamilyStore cfs =
Keyspace.open(KEYSPACE).getColumnFamilyStore("cf");
+ Assert.assertFalse("All SSTables should be in the correct
location",
+ cfs.hasMisplacedSSTables());
+ });
+ }
+
+ // by moving all sstables from the first data directory to the second.
+ private void setupMisplacedSSTables()
+ {
+ NODE.runOnInstance(() -> {
+ ColumnFamilyStore cfs =
Keyspace.open(KEYSPACE).getColumnFamilyStore("cf");
+ Assert.assertNotEquals(0, cfs.getLiveSSTables().size());
+ Iterator<SSTableReader> sstables =
cfs.getLiveSSTables().iterator();
+ // finding 2 descriptors that live in different data directory
+ Descriptor first = sstables.next().descriptor;
+ Descriptor second = null;
+ while (sstables.hasNext() && second == null) {
+ second = sstables.next().descriptor;
+ if (first.directory.equals(second.directory))
+ second = null;
+ }
+ Assert.assertNotNull("There should be SSTables in multiple data
directories", second);
+ // getting a new file index in order to move SSTable between
directories.
+ second = cfs.newSSTableDescriptor(second.directory);
+ // now we just move all sstables from first to second
+ for (Component component : SSTableReader.componentsFor(first))
+ {
+ File file = new File(first.filenameFor(component));
+ if (file.exists())
+ {
+ try
+ {
+ Files.copy(file.toPath(), new
File(second.filenameFor(component)).toPath());
+ }
+ catch (IOException e)
+ {
+ throw new RuntimeException("Something wrong with
copying sstables", e);
+ }
+ }
+ }
+ ColumnFamilyStore.loadNewSSTables(KEYSPACE, "cf");
+ });
+ }
+}
diff --git
a/test/unit/org/apache/cassandra/tools/nodetool/stats/NodetoolTableStatsTest.java
b/test/unit/org/apache/cassandra/tools/nodetool/stats/NodetoolTableStatsTest.java
index 528a6ca..a459f0f 100644
---
a/test/unit/org/apache/cassandra/tools/nodetool/stats/NodetoolTableStatsTest.java
+++
b/test/unit/org/apache/cassandra/tools/nodetool/stats/NodetoolTableStatsTest.java
@@ -62,16 +62,16 @@ public class NodetoolTableStatsTest extends CQLTester
" nodetool tablestats - Print statistics on
tables\n" +
"\n" +
"SYNOPSIS\n" +
- " nodetool [(-h <host> | --host <host>)] [(-p
<port> | --port <port>)]\n" +
- " [(-pp | --print-port)] [(-pw
<password> | --password <password>)]\n" +
- " [(-pwf <passwordFilePath> |
--password-file <passwordFilePath>)]\n" +
- " [(-u <username> | --username
<username>)] tablestats\n" +
- " [(-F <format> | --format <format>)]
[(-H | --human-readable)] [-i]\n" +
- " [(-s <sort_key> | --sort <sort_key>)]
[(-t <top> | --top <top>)] [--]\n" +
- " [<keyspace.table>...]\n" +
+ " nodetool [(-h <host> | --host <host>)] [(-p
<port> | --port <port>)]\n" +
+ " [(-pp | --print-port)] [(-pw
<password> | --password <password>)]\n" +
+ " [(-pwf <passwordFilePath> |
--password-file <passwordFilePath>)]\n" +
+ " [(-u <username> | --username
<username>)] tablestats\n" +
+ " [(-F <format> | --format <format>)]
[(-H | --human-readable)] [-i]\n" +
+ " [(-l | --sstable-location-check)]
[(-s <sort_key> | --sort <sort_key>)]\n" +
+ " [(-t <top> | --top <top>)] [--]
[<keyspace.table>...]\n" +
"\n" +
- "OPTIONS\n" +
- " -F <format>, --format <format>\n" +
+ "OPTIONS\n" +
+ " -F <format>, --format <format>\n" +
" Output format (json, yaml)\n" +
"\n" +
" -h <host>, --host <host>\n" +
@@ -81,7 +81,10 @@ public class NodetoolTableStatsTest extends CQLTester
" Display bytes in human readable form,
i.e. KiB, MiB, GiB, TiB\n" +
"\n" +
" -i\n" +
- " Ignore the list of tables and display the
remaining tables\n" +
+ " Ignore the list of tables and display the
remaining tables\n" +
+ "\n" +
+ " -l, --sstable-location-check\n" +
+ " Check whether or not the SSTables are in
the correct location.\n" +
"\n" +
" -p <port>, --port <port>\n" +
" Remote jmx agent port number\n" +
@@ -167,7 +170,7 @@ public class NodetoolTableStatsTest extends CQLTester
{
Arrays.asList("-H", "--human-readable").forEach(arg -> {
ToolResult tool = ToolRunner.invokeNodetool("tablestats", arg);
- assertThat("Arg: [" + arg + "]", tool.getStdout(),
CoreMatchers.containsString(" KiB"));
+ assertThat(argFormat(arg), tool.getStdout(),
CoreMatchers.containsString(" KiB"));
assertTrue(String.format("Expected empty stderr for option [%s]
but found: %s",
arg,
tool.getCleanedStderr()),
@@ -196,11 +199,11 @@ public class NodetoolTableStatsTest extends CQLTester
while (m.find())
sorted.add(m.group(1));
- assertNotEquals("Arg: [" + arg + "]", orig, sorted);
+ assertNotEquals(argFormat(arg), orig, sorted);
Collections.sort(orig);
Collections.sort(sorted);
- assertEquals("Arg: [" + arg + "]", orig, sorted);
- assertTrue("Arg: [" + arg + "]",
tool.getCleanedStderr().isEmpty());
+ assertEquals(argFormat(arg), orig, sorted);
+ assertTrue(argFormat(arg), tool.getCleanedStderr().isEmpty());
assertEquals(0, tool.getExitCode());
});
@@ -215,9 +218,9 @@ public class NodetoolTableStatsTest extends CQLTester
{
Arrays.asList("-t", "--top").forEach(arg -> {
ToolResult tool = ToolRunner.invokeNodetool("tablestats", "-s",
"table_name", arg, "1");
- assertEquals("Arg: [" + arg + "]",
StringUtils.countMatches(tool.getStdout(), "Table:"), 1);
- assertTrue("Arg: [" + arg + "]",
tool.getCleanedStderr().isEmpty());
- assertEquals("Arg: [" + arg + "]", 0, tool.getExitCode());
+ assertEquals(argFormat(arg),
StringUtils.countMatches(tool.getStdout(), "Table:"), 1);
+ assertTrue(argFormat(arg), tool.getCleanedStderr().isEmpty());
+ assertEquals(argFormat(arg), 0, tool.getExitCode());
});
ToolResult tool = ToolRunner.invokeNodetool("tablestats", "-s",
"table_name", "-t", "-1");
@@ -225,4 +228,25 @@ public class NodetoolTableStatsTest extends CQLTester
tool.assertCleanStdErr();
assertEquals(1, tool.getExitCode());
}
+
+ @Test
+ public void testSSTableLocationCheckArg()
+ {
+ Arrays.asList("-l", "--sstable-location-check").forEach(arg -> {
+ ToolResult tool = ToolRunner.invokeNodetool("tablestats", arg,
"system.local");
+ assertEquals(argFormat(arg),
StringUtils.countMatches(tool.getStdout(), "SSTables in correct location: "),
1);
+ assertTrue(argFormat(arg), tool.getCleanedStderr().isEmpty());
+ assertEquals(argFormat(arg), 0, tool.getExitCode());
+ });
+
+ ToolResult tool = ToolRunner.invokeNodetool("tablestats",
"system.local");
+ assertThat(tool.getStdout(),
CoreMatchers.not(CoreMatchers.containsString("SSTables in correct location:
")));
+ tool.assertCleanStdErr();
+ assertEquals(0, tool.getExitCode());
+ }
+
+ private String argFormat(String arg)
+ {
+ return "Arg: [" + arg + ']';
+ }
}
diff --git
a/test/unit/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinterTest.java
b/test/unit/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinterTest.java
index 92c29f5..cc2caa3 100644
---
a/test/unit/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinterTest.java
+++
b/test/unit/org/apache/cassandra/tools/nodetool/stats/TableStatsPrinterTest.java
@@ -365,7 +365,7 @@ public class TableStatsPrinterTest extends
TableStatsTestBase
public TestTableStatsHolder(List<StatsKeyspace> testKeyspaces, String
sortKey, int top)
{
- super(null, false, false, new ArrayList<>(), sortKey, top);
+ super(null, false, false, new ArrayList<>(), sortKey, top, false);
this.keyspaces.clear();
this.keyspaces.addAll(testKeyspaces);
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]