Merge branch 'cassandra-3.0' into cassandra-3.11

This commit is contained in:
Marcus Eriksson 2017-10-04 08:18:36 +02:00
commit f5bc42996b
3 changed files with 54 additions and 6 deletions

View File

@ -12,6 +12,7 @@
* Duplicate the buffer before passing it to analyser in SASI operation (CASSANDRA-13512)
* Properly evict pstmts from prepared statements cache (CASSANDRA-13641)
Merged from 3.0:
* Deserialise sstable metadata in nodetool verify (CASSANDRA-13922)
* Improve TRUNCATE performance (CASSANDRA-13909)
* Implement short read protection on partition boundaries (CASSANDRA-13595)
* Fix ISE thrown by UPI.Serializer.hasNext() for some SELECT queries (CASSANDRA-13911)

View File

@ -26,6 +26,9 @@ import org.apache.cassandra.io.sstable.Component;
import org.apache.cassandra.io.sstable.CorruptSSTableException;
import org.apache.cassandra.io.sstable.SSTableIdentityIterator;
import org.apache.cassandra.io.sstable.format.SSTableReader;
import org.apache.cassandra.io.sstable.metadata.MetadataComponent;
import org.apache.cassandra.io.sstable.metadata.MetadataType;
import org.apache.cassandra.io.sstable.metadata.ValidationMetadata;
import org.apache.cassandra.io.util.DataIntegrityMetadata;
import org.apache.cassandra.io.util.DataIntegrityMetadata.FileDigestValidator;
import org.apache.cassandra.io.util.FileUtils;
@ -58,7 +61,6 @@ public class Verifier implements Closeable
private final RowIndexEntry.IndexSerializer rowIndexEntrySerializer;
private int goodRows;
private int badRows;
private final OutputHandler outputHandler;
private FileDigestValidator validator;
@ -89,6 +91,20 @@ public class Verifier implements Closeable
long rowStart = 0;
outputHandler.output(String.format("Verifying %s (%s)", sstable, FBUtilities.prettyPrintMemory(dataFile.length())));
outputHandler.output(String.format("Deserializing sstable metadata for %s ", sstable));
try
{
EnumSet<MetadataType> types = EnumSet.of(MetadataType.VALIDATION, MetadataType.STATS, MetadataType.HEADER);
Map<MetadataType, MetadataComponent> sstableMetadata = sstable.descriptor.getMetadataSerializer().deserialize(sstable.descriptor, types);
if (sstableMetadata.containsKey(MetadataType.VALIDATION) &&
!((ValidationMetadata)sstableMetadata.get(MetadataType.VALIDATION)).partitioner.equals(sstable.getPartitioner().getClass().getCanonicalName()))
throw new IOException("Partitioner does not match validation metadata");
}
catch (Throwable t)
{
outputHandler.debug(t.getMessage());
markAndThrow(false);
}
outputHandler.output(String.format("Checking computed hash of %s ", sstable));
@ -187,7 +203,7 @@ public class Verifier implements Closeable
if (key == null || dataSize > dataFile.length())
markAndThrow();
//mimic the scrub read path
//mimic the scrub read path, intentionally unused
try (UnfilteredRowIterator iterator = SSTableIdentityIterator.create(sstable, dataFile, key))
{
}
@ -204,7 +220,6 @@ public class Verifier implements Closeable
}
catch (Throwable th)
{
badRows++;
markAndThrow();
}
}
@ -235,8 +250,14 @@ public class Verifier implements Closeable
private void markAndThrow() throws IOException
{
sstable.descriptor.getMetadataSerializer().mutateRepairedAt(sstable.descriptor, ActiveRepairService.UNREPAIRED_SSTABLE);
throw new CorruptSSTableException(new Exception(String.format("Invalid SSTable %s, please force repair", sstable.getFilename())), sstable.getFilename());
markAndThrow(true);
}
private void markAndThrow(boolean mutateRepaired) throws IOException
{
if (mutateRepaired) // if we are able to mutate repaired flag, an incremental repair should be enough
sstable.descriptor.getMetadataSerializer().mutateRepairedAt(sstable.descriptor, ActiveRepairService.UNREPAIRED_SSTABLE);
throw new CorruptSSTableException(new Exception(String.format("Invalid SSTable %s, please force %srepair", sstable.getFilename(), mutateRepaired ? "" : "a full ")), sstable.getFilename());
}
public CompactionInfo.Holder getVerifyInfo()

View File

@ -31,6 +31,7 @@ import org.apache.cassandra.db.marshal.UUIDType;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.cassandra.exceptions.WriteTimeoutException;
import org.apache.cassandra.io.FSWriteError;
import org.apache.cassandra.io.sstable.Component;
import org.apache.cassandra.io.sstable.CorruptSSTableException;
import org.apache.cassandra.io.sstable.format.SSTableReader;
import org.apache.cassandra.io.util.FileUtils;
@ -344,9 +345,34 @@ public class VerifyTest
}
fail("Expected a CorruptSSTableException to be thrown");
}
}
@Test(expected = CorruptSSTableException.class)
public void testVerifyBrokenSSTableMetadata() throws IOException, WriteTimeoutException
{
CompactionManager.instance.disableAutoCompaction();
Keyspace keyspace = Keyspace.open(KEYSPACE);
ColumnFamilyStore cfs = keyspace.getColumnFamilyStore(CORRUPT_CF2);
fillCF(cfs, 2);
Util.getAll(Util.cmd(cfs).build());
SSTableReader sstable = cfs.getLiveSSTables().iterator().next();
String filenameToCorrupt = sstable.descriptor.filenameFor(Component.STATS);
RandomAccessFile file = new RandomAccessFile(filenameToCorrupt, "rw");
file.seek(0);
file.writeBytes(StringUtils.repeat('z', 2));
file.close();
try (Verifier verifier = new Verifier(cfs, sstable, false))
{
verifier.verify(false);
}
}
protected void fillCF(ColumnFamilyStore cfs, int partitionsPerSSTable)
{
for (int i = 0; i < partitionsPerSSTable; i++)