diff --git a/CHANGES.txt b/CHANGES.txt index 7863d56e3f..ac3a1574d6 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,5 @@ 1.1.6 + * fix commitlog replay for nanotime-infected sstables (CASSANDRA-4782) * preflight check ttl for maximum of 20 years (CASSANDRA-4771) * Fix HH to compact with correct gcBefore, which avoids wiping out undelivered hints (CASSANDRA-4772) diff --git a/NEWS.txt b/NEWS.txt index a2d0ce1952..667a055dbd 100644 --- a/NEWS.txt +++ b/NEWS.txt @@ -14,8 +14,10 @@ by version X, but the inverse is not necessarily the case.) Upgrading --------- - - Nothing specific to this release, but please see 1.1 if you are upgrading - from a previous version. + - If you are using counters, you should drain existing Cassandra nodes + prior to the upgrade to prevent overcount during commitlog replay + (see CASSANDRA-4782). For non-counter uses, drain is not required + but is a good practice to minimize restart time. 1.1.5 diff --git a/src/java/org/apache/cassandra/io/sstable/Descriptor.java b/src/java/org/apache/cassandra/io/sstable/Descriptor.java index d35865c692..f4663b735c 100644 --- a/src/java/org/apache/cassandra/io/sstable/Descriptor.java +++ b/src/java/org/apache/cassandra/io/sstable/Descriptor.java @@ -59,7 +59,8 @@ public class Descriptor // hc (1.0.4): records partitioner in metadata component // hd (1.0.10): includes row tombstones in maxtimestamp // he (1.1.3): includes ancestors generation in metadata component - public static final String CURRENT_VERSION = "he"; + // hf (1.1.6): marker that replay position corresponds to 1.1.5+ millis-based id (see CASSANDRA-4782) + public static final String CURRENT_VERSION = "hf"; public final File directory; /** version has the following format: [a-z]+ */ @@ -76,6 +77,7 @@ public class Descriptor public final boolean isLatestVersion; public final boolean usesOldBloomFilter; public final boolean metadataIncludesReplayPosition; + public final boolean metadataIncludesModernReplayPosition; public final boolean tracksMaxTimestamp; public final boolean hasCompressionRatio; public final boolean hasPartitioner; @@ -109,6 +111,7 @@ public class Descriptor hasCompressionRatio = version.compareTo("hb") >= 0; hasPartitioner = version.compareTo("hc") >= 0; hasAncestors = version.compareTo("he") >= 0; + metadataIncludesModernReplayPosition = version.compareTo("hf") >= 0; isLatestVersion = version.compareTo(CURRENT_VERSION) == 0; } diff --git a/src/java/org/apache/cassandra/io/sstable/SSTableMetadata.java b/src/java/org/apache/cassandra/io/sstable/SSTableMetadata.java index 147f2b2376..302fb50cba 100644 --- a/src/java/org/apache/cassandra/io/sstable/SSTableMetadata.java +++ b/src/java/org/apache/cassandra/io/sstable/SSTableMetadata.java @@ -217,6 +217,12 @@ public class SSTableMetadata ReplayPosition replayPosition = desc.metadataIncludesReplayPosition ? ReplayPosition.serializer.deserialize(dis) : ReplayPosition.NONE; + if (!desc.metadataIncludesModernReplayPosition) + { + // replay position may be "from the future" thanks to older versions generating them with nanotime. + // make sure we don't omit replaying something that we should. see CASSANDRA-4782 + replayPosition = ReplayPosition.NONE; + } long maxTimestamp = desc.containsTimestamp() ? dis.readLong() : Long.MIN_VALUE; if (!desc.tracksMaxTimestamp) // see javadoc to Descriptor.containsTimestamp maxTimestamp = Long.MIN_VALUE;