Skip to content

Commit

Permalink
Include checksums in CorruptBlockException when relevant (#1291)
Browse files Browse the repository at this point in the history
This additional metadata is somewhat valuable in the context of troubleshooting. Recently, we had an issue where the checksum itself was not (over)written and so it was stored as 0. In many cases, this won't be helpful, but since it is cheap and could be helpful, I propose adding some additional metadata when checksums don't match.
  • Loading branch information
michaeljmarshall authored Sep 19, 2024
1 parent b7def63 commit 5ea584d
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -310,8 +310,10 @@ private synchronized void doResetAndTruncate(DataPosition mark)
crcCheckBuffer.clear();
readChannel.read(crcCheckBuffer);
crcCheckBuffer.flip();
if (crcCheckBuffer.getInt() != (int) checksum.getValue())
throw new CorruptBlockException(getFile().toString(), chunkOffset, chunkSize);
int storedChecksum = crcCheckBuffer.getInt();
int computedChecksum = (int) checksum.getValue();
if (storedChecksum != computedChecksum)
throw new CorruptBlockException(getFile().toString(), chunkOffset, chunkSize, storedChecksum, computedChecksum);
}
catch (CorruptBlockException e)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,16 @@ public CorruptBlockException(String filePath, long offset, int length, Throwable
{
super(String.format("(%s): corruption detected, chunk at %d of length %d.", filePath, offset, length), cause);
}

public CorruptBlockException(String filePath, CompressionMetadata.Chunk chunk, int storedChecksum, int calculatedChecksum)
{
this(filePath, chunk.offset, chunk.length, storedChecksum, calculatedChecksum);
}

public CorruptBlockException(String filePath, long offset, int length, int storedChecksum, int calculatedChecksum)
{
super(String.format("(%s): corruption detected, chunk at %d of length %d has mismatched checksums. Expected %d, but calculated %d",
filePath, offset, length, storedChecksum, calculatedChecksum));
}

}
16 changes: 10 additions & 6 deletions src/java/org/apache/cassandra/io/util/CompressedChunkReader.java
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,9 @@ public void readChunk(long position, ByteBuffer uncompressed)
int checksum = (int) ChecksumType.CRC32.of(compressed);

compressed.limit(length);
if (compressed.getInt() != checksum)
throw new CorruptBlockException(channel.filePath(), chunk);
int storedChecksum = compressed.getInt();
if (storedChecksum != checksum)
throw new CorruptBlockException(channel.filePath(), chunk, storedChecksum, checksum);

compressed.position(0).limit(chunk.length);
}
Expand All @@ -166,9 +167,11 @@ public void readChunk(long position, ByteBuffer uncompressed)

ByteBuffer scratch = bufferHolder.getBuffer(Integer.BYTES);

if (channel.read(scratch, chunkOffset + chunk.length) != Integer.BYTES
|| scratch.getInt(0) != checksum)
if (channel.read(scratch, chunkOffset + chunk.length) != Integer.BYTES)
throw new CorruptBlockException(channel.filePath(), chunk);
int storedChecksum = scratch.getInt(0);
if (storedChecksum != checksum)
throw new CorruptBlockException(channel.filePath(), chunk, storedChecksum, checksum);
}
}
uncompressed.flip();
Expand Down Expand Up @@ -231,8 +234,9 @@ public void readChunk(long position, ByteBuffer uncompressed)
int checksum = (int) ChecksumType.CRC32.of(compressedChunk);

compressedChunk.limit(compressedChunk.capacity());
if (compressedChunk.getInt() != checksum)
throw new CorruptBlockException(channel.filePath(), chunk);
int storedChecksum = compressedChunk.getInt();
if (storedChecksum != checksum)
throw new CorruptBlockException(channel.filePath(), chunk, storedChecksum, checksum);

compressedChunk.position(chunkOffsetInSegment).limit(chunkOffsetInSegment + chunk.length);
}
Expand Down

0 comments on commit 5ea584d

Please sign in to comment.