Handle repeat open bound from SRP in read repair patch by Aleksey Yeschenko; reviewed by Sylvain Lebresne for CASSANDRA-14330
Project: http://git-wip-us.apache.org/repos/asf/cassandra/repo Commit: http://git-wip-us.apache.org/repos/asf/cassandra/commit/3153c630 Tree: http://git-wip-us.apache.org/repos/asf/cassandra/tree/3153c630 Diff: http://git-wip-us.apache.org/repos/asf/cassandra/diff/3153c630 Branch: refs/heads/cassandra-3.0 Commit: 3153c630c499edf3c523d8e5a3db6f1d6c52ad4c Parents: 15bd10a Author: Aleksey Yeschenko <alek...@yeschenko.com> Authored: Sat Mar 10 22:28:07 2018 +0000 Committer: Aleksey Yeshchenko <alek...@apple.com> Committed: Wed Mar 21 15:10:12 2018 +0000 ---------------------------------------------------------------------- CHANGES.txt | 1 + .../org/apache/cassandra/db/ReadResponse.java | 22 +++++++++++++++- .../db/rows/RangeTombstoneBoundMarker.java | 2 +- .../db/rows/RangeTombstoneBoundaryMarker.java | 5 +++- .../apache/cassandra/service/DataResolver.java | 27 +++++++++++++++----- 5 files changed, 48 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cassandra/blob/3153c630/CHANGES.txt ---------------------------------------------------------------------- diff --git a/CHANGES.txt b/CHANGES.txt index b967580..d701a22 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 3.0.17 + * Handle repeat open bound from SRP in read repair (CASSANDRA-14330) * Use zero as default score in DynamicEndpointSnitch (CASSANDRA-14252) * Respect max hint window when hinting for LWT (CASSANDRA-14215) * Adding missing WriteType enum values to v3, v4, and v5 spec (CASSANDRA-13697) http://git-wip-us.apache.org/repos/asf/cassandra/blob/3153c630/src/java/org/apache/cassandra/db/ReadResponse.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/ReadResponse.java b/src/java/org/apache/cassandra/db/ReadResponse.java index c59d00a..bc44a1b 100644 --- a/src/java/org/apache/cassandra/db/ReadResponse.java +++ b/src/java/org/apache/cassandra/db/ReadResponse.java @@ -107,13 +107,33 @@ public abstract class ReadResponse try (UnfilteredRowIterator partition = iter.next()) { if (partition.partitionKey().equals(key)) - return ImmutableBTreePartition.create(partition).toString(); + return toDebugString(partition, command.metadata()); } } } return "<key " + key + " not found>"; } + private String toDebugString(UnfilteredRowIterator partition, CFMetaData metadata) + { + StringBuilder sb = new StringBuilder(); + + sb.append(String.format("[%s.%s] key=%s partition_deletion=%s columns=%s", + metadata.ksName, + metadata.cfName, + metadata.getKeyValidator().getString(partition.partitionKey().getKey()), + partition.partitionLevelDeletion(), + partition.columns())); + + if (partition.staticRow() != Rows.EMPTY_STATIC_ROW) + sb.append("\n ").append(partition.staticRow().toString(metadata, true)); + + while (partition.hasNext()) + sb.append("\n ").append(partition.next().toString(metadata, true)); + + return sb.toString(); + } + protected static ByteBuffer makeDigest(UnfilteredPartitionIterator iterator, ReadCommand command) { MessageDigest digest = FBUtilities.threadLocalMD5Digest(); http://git-wip-us.apache.org/repos/asf/cassandra/blob/3153c630/src/java/org/apache/cassandra/db/rows/RangeTombstoneBoundMarker.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/rows/RangeTombstoneBoundMarker.java b/src/java/org/apache/cassandra/db/rows/RangeTombstoneBoundMarker.java index 6f4afa5..0079114 100644 --- a/src/java/org/apache/cassandra/db/rows/RangeTombstoneBoundMarker.java +++ b/src/java/org/apache/cassandra/db/rows/RangeTombstoneBoundMarker.java @@ -140,7 +140,7 @@ public class RangeTombstoneBoundMarker extends AbstractRangeTombstoneMarker public String toString(CFMetaData metadata) { - return "Marker " + bound.toString(metadata) + '@' + deletion.markedForDeleteAt(); + return String.format("Marker %s@%d/%d", bound.toString(metadata), deletion.markedForDeleteAt(), deletion.localDeletionTime()); } @Override http://git-wip-us.apache.org/repos/asf/cassandra/blob/3153c630/src/java/org/apache/cassandra/db/rows/RangeTombstoneBoundaryMarker.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/db/rows/RangeTombstoneBoundaryMarker.java b/src/java/org/apache/cassandra/db/rows/RangeTombstoneBoundaryMarker.java index 0683d76..c4bc2f2 100644 --- a/src/java/org/apache/cassandra/db/rows/RangeTombstoneBoundaryMarker.java +++ b/src/java/org/apache/cassandra/db/rows/RangeTombstoneBoundaryMarker.java @@ -153,7 +153,10 @@ public class RangeTombstoneBoundaryMarker extends AbstractRangeTombstoneMarker public String toString(CFMetaData metadata) { - return String.format("Marker %s@%d-%d", bound.toString(metadata), endDeletion.markedForDeleteAt(), startDeletion.markedForDeleteAt()); + return String.format("Marker %s@%d/%d-%d/%d", + bound.toString(metadata), + endDeletion.markedForDeleteAt(), endDeletion.localDeletionTime(), + startDeletion.markedForDeleteAt(), startDeletion.localDeletionTime()); } @Override http://git-wip-us.apache.org/repos/asf/cassandra/blob/3153c630/src/java/org/apache/cassandra/service/DataResolver.java ---------------------------------------------------------------------- diff --git a/src/java/org/apache/cassandra/service/DataResolver.java b/src/java/org/apache/cassandra/service/DataResolver.java index f02b565..2252913 100644 --- a/src/java/org/apache/cassandra/service/DataResolver.java +++ b/src/java/org/apache/cassandra/service/DataResolver.java @@ -331,8 +331,10 @@ public class DataResolver extends ResponseResolver // The following can be pretty verbose, but it's really only triggered if a bug happen, so we'd // rather get more info to debug than not. CFMetaData table = command.metadata(); - String details = String.format("Error merging RTs on %s.%s: merged=%s, versions=%s, sources={%s}, responses:%n %s", + String details = String.format("Error merging RTs on %s.%s: command=%s, reversed=%b, merged=%s, versions=%s, sources={%s}, responses:%n %s", table.ksName, table.cfName, + command.toCQLString(), + isReversed, merged == null ? "null" : merged.toString(table), '[' + Joiner.on(", ").join(Iterables.transform(Arrays.asList(versions), rt -> rt == null ? "null" : rt.toString(table))) + ']', Arrays.toString(sources), @@ -395,11 +397,24 @@ public class DataResolver extends ResponseResolver DeletionTime partitionRepairDeletion = partitionLevelRepairDeletion(i); if (markerToRepair[i] == null && currentDeletion.supersedes(partitionRepairDeletion)) { - // Since there is an ongoing merged deletion, the only way we don't have an open repair for - // this source is that it had a range open with the same deletion as current and it's - // closing it. - assert marker.isClose(isReversed) && currentDeletion.equals(marker.closeDeletionTime(isReversed)) - : String.format("currentDeletion=%s, marker=%s", currentDeletion, marker.toString(command.metadata())); + /* + * Since there is an ongoing merged deletion, the only two ways we don't have an open repair for + * this source are that: + * + * 1) it had a range open with the same deletion as current marker, and the marker is coming from + * a short read protection response - repeating the open RT bound, or + * 2) it had a range open with the same deletion as current marker, and the marker is closing it. + */ + if (!marker.isBoundary() && marker.isOpen(isReversed)) // (1) + { + assert currentDeletion.equals(marker.openDeletionTime(isReversed)) + : String.format("currentDeletion=%s, marker=%s", currentDeletion, marker.toString(command.metadata())); + } + else // (2) + { + assert marker.isClose(isReversed) && currentDeletion.equals(marker.closeDeletionTime(isReversed)) + : String.format("currentDeletion=%s, marker=%s", currentDeletion, marker.toString(command.metadata())); + } // and so unless it's a boundary whose opening deletion time is still equal to the current // deletion (see comment above for why this can actually happen), we have to repair the source --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org