diff --git a/CHANGES.txt b/CHANGES.txt index 4eb03e586f..c38b69b171 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -20,8 +20,8 @@ * Update jackson JSON jars (CASSANDRA-13949) * Avoid locks when checking LCS fanout and if we should defrag (CASSANDRA-13930) * Correctly count range tombstones in traces and tombstone thresholds (CASSANDRA-8527) - Merged from 3.0: + * Use the correct digest file and reload sstable metadata in nodetool verify (CASSANDRA-14217) * Handle failure when mutating repaired status in Verifier (CASSANDRA-13933) * Set encoding for javadoc generation (CASSANDRA-14154) * Fix index target computation for dense composite tables with dropped compact storage (CASSANDRA-14104) diff --git a/src/java/org/apache/cassandra/db/compaction/Verifier.java b/src/java/org/apache/cassandra/db/compaction/Verifier.java index 44a585078b..f0309b7829 100644 --- a/src/java/org/apache/cassandra/db/compaction/Verifier.java +++ b/src/java/org/apache/cassandra/db/compaction/Verifier.java @@ -260,6 +260,8 @@ public class Verifier implements Closeable try { sstable.descriptor.getMetadataSerializer().mutateRepairedAt(sstable.descriptor, ActiveRepairService.UNREPAIRED_SSTABLE); + sstable.reloadSSTableMetadata(); + cfs.getTracker().notifySSTableRepairedStatusChanged(Collections.singleton(sstable)); } catch(IOException ioe) { diff --git a/src/java/org/apache/cassandra/io/util/DataIntegrityMetadata.java b/src/java/org/apache/cassandra/io/util/DataIntegrityMetadata.java index cee23c9881..9afd0c0616 100644 --- a/src/java/org/apache/cassandra/io/util/DataIntegrityMetadata.java +++ b/src/java/org/apache/cassandra/io/util/DataIntegrityMetadata.java @@ -100,7 +100,7 @@ public class DataIntegrityMetadata { this.descriptor = descriptor; checksum = descriptor.version.uncompressedChecksumType().newInstance(); - digestReader = RandomAccessReader.open(new File(descriptor.filenameFor(Component.digestFor(descriptor.version.uncompressedChecksumType())))); + digestReader = RandomAccessReader.open(new File(descriptor.filenameFor(descriptor.digestComponent))); dataReader = RandomAccessReader.open(new File(descriptor.filenameFor(Component.DATA))); try { diff --git a/test/unit/org/apache/cassandra/db/VerifyTest.java b/test/unit/org/apache/cassandra/db/VerifyTest.java index 6808c47f39..a332f743df 100644 --- a/test/unit/org/apache/cassandra/db/VerifyTest.java +++ b/test/unit/org/apache/cassandra/db/VerifyTest.java @@ -25,6 +25,7 @@ import org.apache.cassandra.SchemaLoader; import org.apache.cassandra.Util; import org.apache.cassandra.cache.ChunkCache; import org.apache.cassandra.UpdateBuilder; +import org.apache.cassandra.db.compaction.AbstractCompactionStrategy; import org.apache.cassandra.db.compaction.CompactionManager; import org.apache.cassandra.db.compaction.Verifier; import org.apache.cassandra.db.marshal.UUIDType; @@ -45,9 +46,14 @@ import org.junit.runner.RunWith; import java.io.*; import java.nio.file.Files; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutionException; import java.util.zip.CRC32; import java.util.zip.CheckedInputStream; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @RunWith(OrderedJUnit4ClassRunner.class) @@ -372,6 +378,39 @@ public class VerifyTest } } + @Test + public void testMutateRepair() throws IOException, ExecutionException, InterruptedException + { + CompactionManager.instance.disableAutoCompaction(); + Keyspace keyspace = Keyspace.open(KEYSPACE); + ColumnFamilyStore cfs = keyspace.getColumnFamilyStore(CORRUPT_CF2); + + fillCF(cfs, 2); + + SSTableReader sstable = cfs.getLiveSSTables().iterator().next(); + sstable.descriptor.getMetadataSerializer().mutateRepairedAt(sstable.descriptor, 1); + sstable.reloadSSTableMetadata(); + cfs.getTracker().notifySSTableRepairedStatusChanged(Collections.singleton(sstable)); + assertTrue(sstable.isRepaired()); + cfs.forceMajorCompaction(); + + sstable = cfs.getLiveSSTables().iterator().next(); + Long correctChecksum; + try (RandomAccessFile file = new RandomAccessFile(sstable.descriptor.filenameFor(sstable.descriptor.digestComponent), "rw")) + { + correctChecksum = Long.parseLong(file.readLine()); + } + writeChecksum(++correctChecksum, sstable.descriptor.filenameFor(sstable.descriptor.digestComponent)); + try (Verifier verifier = new Verifier(cfs, sstable, false)) + { + verifier.verify(false); + fail("should be corrupt"); + } + catch (CorruptSSTableException e) + {} + assertFalse(sstable.isRepaired()); + } + protected void fillCF(ColumnFamilyStore cfs, int partitionsPerSSTable) { diff --git a/test/unit/org/apache/cassandra/io/sstable/LegacySSTableTest.java b/test/unit/org/apache/cassandra/io/sstable/LegacySSTableTest.java index d76ccbef4b..478327dbf8 100644 --- a/test/unit/org/apache/cassandra/io/sstable/LegacySSTableTest.java +++ b/test/unit/org/apache/cassandra/io/sstable/LegacySSTableTest.java @@ -40,6 +40,7 @@ import org.apache.cassandra.cql3.QueryProcessor; import org.apache.cassandra.cql3.UntypedResultSet; import org.apache.cassandra.db.ColumnFamilyStore; import org.apache.cassandra.db.Keyspace; +import org.apache.cassandra.db.compaction.Verifier; import org.apache.cassandra.dht.IPartitioner; import org.apache.cassandra.dht.Range; import org.apache.cassandra.dht.Token; @@ -206,6 +207,23 @@ public class LegacySSTableTest Assert.assertEquals(5000, rs.size()); } + @Test + public void verifyOldSSTables() throws Exception + { + for (String legacyVersion : legacyVersions) + { + loadLegacyTables(legacyVersion); + ColumnFamilyStore cfs = Keyspace.open("legacy_tables").getColumnFamilyStore(String.format("legacy_%s_simple", legacyVersion)); + for (SSTableReader sstable : cfs.getLiveSSTables()) + { + try (Verifier verifier = new Verifier(cfs, sstable, false)) + { + verifier.verify(true); + } + } + } + } + private void streamLegacyTables(String legacyVersion) throws Exception { for (int compact = 0; compact <= 1; compact++)