diff --git a/server/src/main/java/org/elasticsearch/index/translog/Checkpoint.java b/server/src/main/java/org/elasticsearch/index/translog/Checkpoint.java index 27ea3e842ef52..523e24d8c57f4 100644 --- a/server/src/main/java/org/elasticsearch/index/translog/Checkpoint.java +++ b/server/src/main/java/org/elasticsearch/index/translog/Checkpoint.java @@ -51,7 +51,6 @@ final class Checkpoint { final long minTranslogGeneration; final long trimmedAboveSeqNo; - private static final int INITIAL_VERSION = 1; // start with 1, just to recognize there was some magic serialization logic before private static final int VERSION_6_0_0 = 2; // introduction of global checkpoints private static final int CURRENT_VERSION = 3; // introduction of trimmed above seq# @@ -63,10 +62,10 @@ final class Checkpoint { + Integer.BYTES // ops + Long.BYTES // offset + Long.BYTES // generation - + Long.BYTES // minimum sequence number, introduced in 6.0.0 - + Long.BYTES // maximum sequence number, introduced in 6.0.0 - + Long.BYTES // global checkpoint, introduced in 6.0.0 - + Long.BYTES // minimum translog generation in the translog - introduced in 6.0.0 + + Long.BYTES // minimum sequence number + + Long.BYTES // maximum sequence number + + Long.BYTES // global checkpoint + + Long.BYTES // minimum translog generation in the translog + Long.BYTES // maximum reachable (trimmed) sequence number, introduced in 6.4.0 + CodecUtil.footerLength(); @@ -75,17 +74,10 @@ final class Checkpoint { + Integer.BYTES // ops + Long.BYTES // offset + Long.BYTES // generation - + Long.BYTES // minimum sequence number, introduced in 6.0.0 - + Long.BYTES // maximum sequence number, introduced in 6.0.0 - + Long.BYTES // global checkpoint, introduced in 6.0.0 - + Long.BYTES // minimum translog generation in the translog - introduced in 6.0.0 - + CodecUtil.footerLength(); - - // size of 5.0.0 checkpoint - static final int V1_FILE_SIZE = CodecUtil.headerLength(CHECKPOINT_CODEC) - + Integer.BYTES // ops - + Long.BYTES // offset - + Long.BYTES // generation + + Long.BYTES // minimum sequence number + + Long.BYTES // maximum sequence number + + Long.BYTES // global checkpoint + + Long.BYTES // minimum translog generation in the translog + CodecUtil.footerLength(); /** @@ -136,7 +128,7 @@ static Checkpoint emptyTranslogCheckpoint(final long offset, final long generati return new Checkpoint(offset, 0, generation, minSeqNo, maxSeqNo, globalCheckpoint, minTranslogGeneration, trimmedAboveSeqNo); } - static Checkpoint readCheckpointV6_4_0(final DataInput in) throws IOException { + static Checkpoint readCheckpointV3(final DataInput in) throws IOException { final long offset = in.readLong(); final int numOps = in.readInt(); final long generation = in.readLong(); @@ -148,7 +140,7 @@ static Checkpoint readCheckpointV6_4_0(final DataInput in) throws IOException { return new Checkpoint(offset, numOps, generation, minSeqNo, maxSeqNo, globalCheckpoint, minTranslogGeneration, trimmedAboveSeqNo); } - static Checkpoint readCheckpointV6_0_0(final DataInput in) throws IOException { + static Checkpoint readCheckpointV2(final DataInput in) throws IOException { final long offset = in.readLong(); final int numOps = in.readInt(); final long generation = in.readLong(); @@ -160,19 +152,6 @@ static Checkpoint readCheckpointV6_0_0(final DataInput in) throws IOException { return new Checkpoint(offset, numOps, generation, minSeqNo, maxSeqNo, globalCheckpoint, minTranslogGeneration, trimmedAboveSeqNo); } - // reads a checksummed checkpoint introduced in ES 5.0.0 - static Checkpoint readCheckpointV5_0_0(final DataInput in) throws IOException { - final long offset = in.readLong(); - final int numOps = in.readInt(); - final long generation = in.readLong(); - final long minSeqNo = SequenceNumbers.NO_OPS_PERFORMED; - final long maxSeqNo = SequenceNumbers.NO_OPS_PERFORMED; - final long globalCheckpoint = SequenceNumbers.UNASSIGNED_SEQ_NO; - final long minTranslogGeneration = -1; - final long trimmedAboveSeqNo = SequenceNumbers.UNASSIGNED_SEQ_NO; - return new Checkpoint(offset, numOps, generation, minSeqNo, maxSeqNo, globalCheckpoint, minTranslogGeneration, trimmedAboveSeqNo); - } - @Override public String toString() { return "Checkpoint{" + @@ -192,17 +171,14 @@ public static Checkpoint read(Path path) throws IOException { try (IndexInput indexInput = dir.openInput(path.getFileName().toString(), IOContext.DEFAULT)) { // We checksum the entire file before we even go and parse it. If it's corrupted we barf right here. CodecUtil.checksumEntireFile(indexInput); - final int fileVersion = CodecUtil.checkHeader(indexInput, CHECKPOINT_CODEC, INITIAL_VERSION, CURRENT_VERSION); - if (fileVersion == INITIAL_VERSION) { - assert indexInput.length() == V1_FILE_SIZE : indexInput.length(); - return Checkpoint.readCheckpointV5_0_0(indexInput); - } else if (fileVersion == VERSION_6_0_0) { + final int fileVersion = CodecUtil.checkHeader(indexInput, CHECKPOINT_CODEC, VERSION_6_0_0, CURRENT_VERSION); + if (fileVersion == VERSION_6_0_0) { assert indexInput.length() == V2_FILE_SIZE : indexInput.length(); - return Checkpoint.readCheckpointV6_0_0(indexInput); + return Checkpoint.readCheckpointV2(indexInput); } else { assert fileVersion == CURRENT_VERSION : fileVersion; assert indexInput.length() == V3_FILE_SIZE : indexInput.length(); - return Checkpoint.readCheckpointV6_4_0(indexInput); + return Checkpoint.readCheckpointV3(indexInput); } } catch (CorruptIndexException | NoSuchFileException | IndexFormatTooOldException | IndexFormatTooNewException e) { throw new TranslogCorruptedException(path.toString(), e); diff --git a/server/src/test/java/org/elasticsearch/index/translog/TranslogTests.java b/server/src/test/java/org/elasticsearch/index/translog/TranslogTests.java index 5c31cfb748a2d..bb3804d3aa49b 100644 --- a/server/src/test/java/org/elasticsearch/index/translog/TranslogTests.java +++ b/server/src/test/java/org/elasticsearch/index/translog/TranslogTests.java @@ -25,6 +25,7 @@ import org.apache.lucene.document.Field; import org.apache.lucene.document.NumericDocValuesField; import org.apache.lucene.document.TextField; +import org.apache.lucene.index.IndexFormatTooOldException; import org.apache.lucene.index.Term; import org.apache.lucene.mockfile.FilterFileChannel; import org.apache.lucene.mockfile.FilterFileSystemProvider; @@ -2791,6 +2792,18 @@ public void testCheckpointOnDiskFull() throws IOException { assertEquals(read, checkpoint); } + public void testLegacyCheckpointVersion() throws IOException { + expectThrows( + TranslogCorruptedException.class, + IndexFormatTooOldException.class, + () -> Checkpoint.read(getDataPath("/org/elasticsearch/index/checkpoint/v1.ckp.binary")) + ); + assertThat(Checkpoint.read(getDataPath("/org/elasticsearch/index/checkpoint/v2.ckp.binary")), + equalTo(new Checkpoint(-1312746831014894010L, 44230819, 4168771208509507653L, 6217263213205155568L, + 8590850694628654668L, 3768575734506660560L, 1476009383806516272L, + SequenceNumbers.UNASSIGNED_SEQ_NO))); + } + /** * Tests that closing views after the translog is fine and we can reopen the translog */ diff --git a/server/src/test/resources/org/elasticsearch/index/checkpoint/v1.ckp.binary b/server/src/test/resources/org/elasticsearch/index/checkpoint/v1.ckp.binary new file mode 100644 index 0000000000000..c3a0a1656cb01 Binary files /dev/null and b/server/src/test/resources/org/elasticsearch/index/checkpoint/v1.ckp.binary differ diff --git a/server/src/test/resources/org/elasticsearch/index/checkpoint/v2.ckp.binary b/server/src/test/resources/org/elasticsearch/index/checkpoint/v2.ckp.binary new file mode 100644 index 0000000000000..91377cef9d66d Binary files /dev/null and b/server/src/test/resources/org/elasticsearch/index/checkpoint/v2.ckp.binary differ