This is an automated email from the ASF dual-hosted git repository.
paulo pushed a commit to branch cassandra-3.11
in repository https://gitbox.apache.org/repos/asf/cassandra.git
The following commit(s) were added to refs/heads/cassandra-3.11 by this push:
new 95a6223 Fix snapshot true size calculation
95a6223 is described below
commit 95a622305722889c321204c4bca68a3517a29aab
Author: Paulo Motta <[email protected]>
AuthorDate: Mon Mar 14 17:17:37 2022 -0300
Fix snapshot true size calculation
Patch by Paulo Motta; Reviewed by Brandon Williams and Benjamin Lerer for
CASSANDRA-17267
---
CHANGES.txt | 1 +
src/java/org/apache/cassandra/db/Directories.java | 7 +--
.../apache/cassandra/db/ColumnFamilyStoreTest.java | 46 +++++++++++++++++++
.../apache/cassandra/index/sasi/SASIIndexTest.java | 51 +++++++++++++---------
4 files changed, 81 insertions(+), 24 deletions(-)
diff --git a/CHANGES.txt b/CHANGES.txt
index a8954b7..df9d4e1 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,4 +1,5 @@
3.11.13
+ * Fix snapshot true size calculation (CASSANDRA-17267)
* Validate existence of DCs when repairing (CASSANDRA-17407)
* dropping of a materialized view creates a snapshot with dropped- prefix
(CASSANDRA-17415)
Merged from 3.0:
diff --git a/src/java/org/apache/cassandra/db/Directories.java
b/src/java/org/apache/cassandra/db/Directories.java
index b5be69b..b37afa5 100644
--- a/src/java/org/apache/cassandra/db/Directories.java
+++ b/src/java/org/apache/cassandra/db/Directories.java
@@ -27,6 +27,7 @@ import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.BiFunction;
+import java.util.stream.Collectors;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Predicate;
@@ -1053,11 +1054,11 @@ public class Directories
private class SSTableSizeSummer extends DirectorySizeCalculator
{
- private final HashSet<File> toSkip;
+ private final Set<String> toSkip;
SSTableSizeSummer(File path, List<File> files)
{
super(path);
- toSkip = new HashSet<>(files);
+ toSkip = files.stream().map(f ->
f.getName()).collect(Collectors.toSet());
}
@Override
@@ -1068,7 +1069,7 @@ public class Directories
return pair != null
&& pair.left.ksname.equals(metadata.ksName)
&& pair.left.cfname.equals(metadata.cfName)
- && !toSkip.contains(file);
+ && !toSkip.contains(file.getName());
}
}
}
diff --git a/test/unit/org/apache/cassandra/db/ColumnFamilyStoreTest.java
b/test/unit/org/apache/cassandra/db/ColumnFamilyStoreTest.java
index a3564bb..3987a29 100644
--- a/test/unit/org/apache/cassandra/db/ColumnFamilyStoreTest.java
+++ b/test/unit/org/apache/cassandra/db/ColumnFamilyStoreTest.java
@@ -30,10 +30,12 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.apache.cassandra.db.lifecycle.LifecycleTransaction;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
+import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -347,6 +349,50 @@ public class ColumnFamilyStoreTest
}
@Test
+ public void testSnapshotSize()
+ {
+ // cleanup any previous test gargbage
+ ColumnFamilyStore cfs =
Keyspace.open(KEYSPACE1).getColumnFamilyStore(CF_STANDARD1);
+ cfs.clearSnapshot("");
+
+ // Add row
+ new RowUpdateBuilder(cfs.metadata, 0, "key1")
+ .clustering("Column1")
+ .add("val", "asdf")
+ .build()
+ .applyUnsafe();
+ cfs.forceBlockingFlush();
+
+ // snapshot
+ cfs.snapshot("basic", null, false, false);
+
+ // check snapshot was created
+ Map<String, Pair<Long, Long>> snapshotDetails =
cfs.getSnapshotDetails();
+ assertThat(snapshotDetails).hasSize(1);
+ assertThat(snapshotDetails).containsKey("basic");
+
+ // check that sizeOnDisk > trueSize = 0
+ Pair<Long, Long> details = snapshotDetails.get("basic");
+ long sizeOnDisk = details.left;
+ long trueSize = details.right;
+ assertThat(sizeOnDisk).isGreaterThan(trueSize);
+ assertThat(trueSize).isZero();
+
+ // compact base table to make trueSize > 0
+ cfs.forceMajorCompaction();
+ LifecycleTransaction.waitForDeletions();
+
+ // sizeOnDisk > trueSize because trueSize does not include
manifest.json
+ // Check that truesize now is > 0
+ snapshotDetails = cfs.getSnapshotDetails();
+ details = snapshotDetails.get("basic");
+ sizeOnDisk = details.left;
+ trueSize = details.right;
+ assertThat(sizeOnDisk).isGreaterThan(trueSize);
+ assertThat(trueSize).isPositive();
+ }
+
+ @Test
public void testBackupAfterFlush() throws Throwable
{
ColumnFamilyStore cfs =
Keyspace.open(KEYSPACE2).getColumnFamilyStore(CF_STANDARD1);
diff --git a/test/unit/org/apache/cassandra/index/sasi/SASIIndexTest.java
b/test/unit/org/apache/cassandra/index/sasi/SASIIndexTest.java
index 6ee53f8..5fbcd8f 100644
--- a/test/unit/org/apache/cassandra/index/sasi/SASIIndexTest.java
+++ b/test/unit/org/apache/cassandra/index/sasi/SASIIndexTest.java
@@ -40,6 +40,7 @@ import org.apache.cassandra.SchemaLoader;
import org.apache.cassandra.config.CFMetaData;
import org.apache.cassandra.config.ColumnDefinition;
import org.apache.cassandra.config.Schema;
+import org.apache.cassandra.db.lifecycle.LifecycleTransaction;
import org.apache.cassandra.index.Index;
import org.apache.cassandra.config.DatabaseDescriptor;
import org.apache.cassandra.cql3.*;
@@ -156,7 +157,6 @@ public class SASIIndexTest
data.put(UUID.randomUUID().toString(),
Pair.create(UUID.randomUUID().toString(), r.nextInt()));
ColumnFamilyStore store = loadData(data, true);
- store.forceMajorCompaction();
Set<SSTableReader> ssTableReaders = store.getLiveSSTables();
Set<Component> sasiComponents = new HashSet<>();
@@ -170,6 +170,10 @@ public class SASIIndexTest
try
{
store.snapshot(snapshotName);
+ // Compact to make true snapshot size != 0
+ store.forceMajorCompaction();
+ LifecycleTransaction.waitForDeletions();
+
FileReader reader = new
FileReader(store.getDirectories().getSnapshotManifestFile(snapshotName));
JSONObject manifest = (JSONObject) new JSONParser().parse(reader);
JSONArray files = (JSONArray) manifest.get("files");
@@ -202,8 +206,7 @@ public class SASIIndexTest
for (Component c : components)
{
- Path componentPath = Paths.get(sstable.descriptor + "-" +
c.name);
- long componentSize = Files.size(componentPath);
+ long componentSize =
Files.size(Paths.get(snapshotSSTable.filenameFor(c)));
if (Component.Type.fromRepresentation(c.name) ==
Component.Type.SECONDARY_INDEX)
indexSize += componentSize;
else
@@ -214,7 +217,7 @@ public class SASIIndexTest
Map<String, Pair<Long, Long>> details = store.getSnapshotDetails();
// check that SASI components are included in the computation of
snapshot size
- Assert.assertEquals((long) details.get(snapshotName).right,
tableSize + indexSize);
+ Assert.assertEquals(tableSize + indexSize, (long)
details.get(snapshotName).right);
}
finally
{
@@ -2636,12 +2639,16 @@ public class SASIIndexTest
private static Set<String> getIndexed(ColumnFamilyStore store,
ColumnFilter columnFilter, int maxResults, Expression... expressions)
{
- return getKeys(getIndexed(store, columnFilter, null, maxResults,
expressions));
+ ReadCommand command = getIndexReadCommand(store, columnFilter, null,
maxResults, expressions);
+ try (ReadExecutionController controller =
command.executionController();
+ UnfilteredPartitionIterator rows =
command.executeLocally(controller))
+ {
+ return getKeys(rows);
+ }
}
private static Set<DecoratedKey> getPaged(ColumnFamilyStore store, int
pageSize, Expression... expressions)
{
- UnfilteredPartitionIterator currentPage;
Set<DecoratedKey> uniqueKeys = new TreeSet<>();
DecoratedKey lastKey = null;
@@ -2650,28 +2657,32 @@ public class SASIIndexTest
do
{
count = 0;
- currentPage = getIndexed(store, ColumnFilter.all(store.metadata),
lastKey, pageSize, expressions);
- if (currentPage == null)
- break;
+ ReadCommand command = getIndexReadCommand(store,
ColumnFilter.all(store.metadata), lastKey, pageSize, expressions);
- while (currentPage.hasNext())
+ try (ReadExecutionController controller =
command.executionController();
+ UnfilteredPartitionIterator currentPage =
command.executeLocally(controller))
{
- try (UnfilteredRowIterator row = currentPage.next())
+ if (currentPage == null)
+ break;
+
+ while (currentPage.hasNext())
{
- uniqueKeys.add(row.partitionKey());
- lastKey = row.partitionKey();
- count++;
+ try (UnfilteredRowIterator row = currentPage.next())
+ {
+ uniqueKeys.add(row.partitionKey());
+ lastKey = row.partitionKey();
+ count++;
+ }
}
}
- currentPage.close();
}
while (count == pageSize);
return uniqueKeys;
}
- private static UnfilteredPartitionIterator getIndexed(ColumnFamilyStore
store, ColumnFilter columnFilter, DecoratedKey startKey, int maxResults,
Expression... expressions)
+ private static ReadCommand getIndexReadCommand(ColumnFamilyStore store,
ColumnFilter columnFilter, DecoratedKey startKey, int maxResults, Expression[]
expressions)
{
DataRange range = (startKey == null)
? DataRange.allData(PARTITIONER)
@@ -2682,15 +2693,13 @@ public class SASIIndexTest
filter.add(store.metadata.getColumnDefinition(e.name), e.op,
e.value);
ReadCommand command =
- PartitionRangeReadCommand.create(false,
- store.metadata,
+ PartitionRangeReadCommand.create(false, store.metadata,
FBUtilities.nowInSeconds(),
columnFilter,
filter,
-
DataLimits.thriftLimits(maxResults, DataLimits.NO_LIMIT),
+ DataLimits.cqlLimits(maxResults),
range);
-
- return command.executeLocally(command.executionController());
+ return command;
}
private static Mutation newMutation(String key, String firstName, String
lastName, int age, long timestamp)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]