-
Notifications
You must be signed in to change notification settings - Fork 25.7k
Add primary term to translog header #29227
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 7 commits
41405e9
fe025b7
8aac0a1
010ceca
46d0c4f
0d914a0
4999d06
6325841
4f1da3c
374eba8
4b7c371
d50d7ed
ad5a212
6ea0779
babba4b
fc8bc06
3a49328
b61d459
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -109,7 +109,7 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC | |
| public static final String CHECKPOINT_FILE_NAME = "translog" + CHECKPOINT_SUFFIX; | ||
|
|
||
| static final Pattern PARSE_STRICT_ID_PATTERN = Pattern.compile("^" + TRANSLOG_FILE_PREFIX + "(\\d+)(\\.tlog)$"); | ||
| public static final int DEFAULT_HEADER_SIZE_IN_BYTES = TranslogWriter.getHeaderLength(UUIDs.randomBase64UUID()); | ||
| public static final int DEFAULT_HEADER_SIZE_IN_BYTES = TranslogHeader.defaultSizeInBytes(UUIDs.randomBase64UUID()); | ||
|
|
||
| // the list of translog readers is guaranteed to be in order of translog generation | ||
| private final List<TranslogReader> readers = new ArrayList<>(); | ||
|
|
@@ -122,6 +122,7 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC | |
| private final AtomicBoolean closed = new AtomicBoolean(); | ||
| private final TranslogConfig config; | ||
| private final LongSupplier globalCheckpointSupplier; | ||
| private final LongSupplier primaryTermSupplier; | ||
| private final String translogUUID; | ||
| private final TranslogDeletionPolicy deletionPolicy; | ||
|
|
||
|
|
@@ -140,10 +141,11 @@ public class Translog extends AbstractIndexShardComponent implements IndexShardC | |
| */ | ||
| public Translog( | ||
| final TranslogConfig config, final String translogUUID, TranslogDeletionPolicy deletionPolicy, | ||
| final LongSupplier globalCheckpointSupplier) throws IOException { | ||
| final LongSupplier globalCheckpointSupplier, final LongSupplier primaryTermSupplier) throws IOException { | ||
| super(config.getShardId(), config.getIndexSettings()); | ||
| this.config = config; | ||
| this.globalCheckpointSupplier = globalCheckpointSupplier; | ||
| this.primaryTermSupplier = primaryTermSupplier; | ||
| this.deletionPolicy = deletionPolicy; | ||
| this.translogUUID = translogUUID; | ||
| bigArrays = config.getBigArrays(); | ||
|
|
@@ -165,7 +167,7 @@ public Translog( | |
| // | ||
| // For this to happen we must have already copied the translog.ckp file into translog-gen.ckp so we first check if that file exists | ||
| // if not we don't even try to clean it up and wait until we fail creating it | ||
| assert Files.exists(nextTranslogFile) == false || Files.size(nextTranslogFile) <= TranslogWriter.getHeaderLength(translogUUID) : "unexpected translog file: [" + nextTranslogFile + "]"; | ||
| assert Files.exists(nextTranslogFile) == false || Files.size(nextTranslogFile) <= TranslogHeader.defaultSizeInBytes(translogUUID) : "unexpected translog file: [" + nextTranslogFile + "]"; | ||
| if (Files.exists(currentCheckpointFile) // current checkpoint is already copied | ||
| && Files.deleteIfExists(nextTranslogFile)) { // delete it and log a warning | ||
| logger.warn("deleted previously created, but not yet committed, next generation [{}]. This can happen due to a tragic exception when creating a new generation", nextTranslogFile.getFileName()); | ||
|
|
@@ -226,6 +228,9 @@ private ArrayList<TranslogReader> recoverFromFiles(Checkpoint checkpoint) throws | |
| minGenerationToRecoverFrom + " checkpoint: " + checkpoint.generation + " - translog ids must be consecutive"); | ||
| } | ||
| final TranslogReader reader = openReader(committedTranslogFile, Checkpoint.read(location.resolve(getCommitCheckpointFileName(i)))); | ||
| assert reader.getPrimaryTerm() <= primaryTermSupplier.getAsLong() : | ||
| "Primary terms go backwards; current term [" + primaryTermSupplier.getAsLong() + "]" + | ||
| "translog path [ " + committedTranslogFile + ", existing term [" + reader.getPrimaryTerm() + "]"; | ||
| foundTranslogs.add(reader); | ||
| logger.debug("recovered local translog from checkpoint {}", checkpoint); | ||
| } | ||
|
|
@@ -269,10 +274,6 @@ private ArrayList<TranslogReader> recoverFromFiles(Checkpoint checkpoint) throws | |
| } | ||
|
|
||
| TranslogReader openReader(Path path, Checkpoint checkpoint) throws IOException { | ||
| return openReader(path, checkpoint, translogUUID); | ||
| } | ||
|
|
||
| private static TranslogReader openReader(Path path, Checkpoint checkpoint, String translogUUID) throws IOException { | ||
| FileChannel channel = FileChannel.open(path, StandardOpenOption.READ); | ||
| try { | ||
| assert Translog.parseIdFromFileName(path) == checkpoint.generation : "expected generation: " + Translog.parseIdFromFileName(path) + " but got: " + checkpoint.generation; | ||
|
|
@@ -459,7 +460,7 @@ TranslogWriter createWriter(long fileGeneration, long initialMinTranslogGen, lon | |
| getChannelFactory(), | ||
| config.getBufferSize(), | ||
| initialMinTranslogGen, initialGlobalCheckpoint, | ||
| globalCheckpointSupplier, this::getMinFileGeneration); | ||
| globalCheckpointSupplier, this::getMinFileGeneration, primaryTermSupplier.getAsLong()); | ||
| } catch (final IOException e) { | ||
| throw new TranslogException(shardId, "failed to create new translog file", e); | ||
| } | ||
|
|
@@ -487,6 +488,10 @@ public Location add(final Operation operation) throws IOException { | |
| final ReleasablePagedBytesReference bytes = out.bytes(); | ||
| try (ReleasableLock ignored = readLock.acquire()) { | ||
| ensureOpen(); | ||
| if (operation.primaryTerm() > current.getPrimaryTerm()) { | ||
| throw new IllegalArgumentException("Operation term is newer than the current term;" | ||
| + "current term[" + current.getPrimaryTerm() + "], operation term[" + operation + "]"); | ||
| } | ||
| return current.add(bytes, operation.seqNo()); | ||
| } | ||
| } catch (final AlreadyClosedException | IOException ex) { | ||
|
|
@@ -993,17 +998,17 @@ public Index(Engine.Index index, Engine.IndexResult indexResult) { | |
| this.autoGeneratedIdTimestamp = index.getAutoGeneratedIdTimestamp(); | ||
| } | ||
|
|
||
| public Index(String type, String id, long seqNo, byte[] source) { | ||
| this(type, id, seqNo, Versions.MATCH_ANY, VersionType.INTERNAL, source, null, null, -1); | ||
| public Index(String type, String id, long seqNo, long primaryTerm, byte[] source) { | ||
| this(type, id, seqNo, primaryTerm, Versions.MATCH_ANY, VersionType.INTERNAL, source, null, null, -1); | ||
| } | ||
|
|
||
| public Index(String type, String id, long seqNo, long version, VersionType versionType, byte[] source, String routing, | ||
| String parent, long autoGeneratedIdTimestamp) { | ||
| public Index(String type, String id, long seqNo, long primaryTerm, long version, VersionType versionType, | ||
| byte[] source, String routing, String parent, long autoGeneratedIdTimestamp) { | ||
| this.type = type; | ||
| this.id = id; | ||
| this.source = new BytesArray(source); | ||
| this.seqNo = seqNo; | ||
| this.primaryTerm = 0; | ||
| this.primaryTerm = primaryTerm; | ||
| this.version = version; | ||
| this.versionType = versionType; | ||
| this.routing = routing; | ||
|
|
@@ -1188,8 +1193,8 @@ public Delete(Engine.Delete delete, Engine.DeleteResult deleteResult) { | |
| } | ||
|
|
||
| /** utility for testing */ | ||
| public Delete(String type, String id, long seqNo, Term uid) { | ||
| this(type, id, uid, seqNo, 0, Versions.MATCH_ANY, VersionType.INTERNAL); | ||
| public Delete(String type, String id, long seqNo, long primaryTerm, Term uid) { | ||
| this(type, id, uid, seqNo, primaryTerm, Versions.MATCH_ANY, VersionType.INTERNAL); | ||
| } | ||
|
|
||
| public Delete(String type, String id, Term uid, long seqNo, long primaryTerm, long version, VersionType versionType) { | ||
|
|
@@ -1393,10 +1398,10 @@ public enum Durability { | |
|
|
||
| } | ||
|
|
||
| private static void verifyChecksum(BufferedChecksumStreamInput in) throws IOException { | ||
| static void verifyChecksum(BufferedChecksumStreamInput in) throws IOException { | ||
| // This absolutely must come first, or else reading the checksum becomes part of the checksum | ||
| long expectedChecksum = in.getChecksum(); | ||
| long readChecksum = in.readInt() & 0xFFFF_FFFFL; | ||
| long readChecksum = Integer.toUnsignedLong(in.readInt()); | ||
| if (readChecksum != expectedChecksum) { | ||
| throw new TranslogCorruptedException("translog stream is corrupted, expected: 0x" + | ||
| Long.toHexString(expectedChecksum) + ", got: 0x" + Long.toHexString(readChecksum)); | ||
|
|
@@ -1679,10 +1684,10 @@ static Checkpoint readCheckpoint(final Path location) throws IOException { | |
| */ | ||
| public static long readGlobalCheckpoint(final Path location, final String expectedTranslogUUID) throws IOException { | ||
| final Checkpoint checkpoint = readCheckpoint(location); | ||
| // We need to open at least translog reader to validate the translogUUID. | ||
| // We need to open at least one translog header to validate the translogUUID. | ||
| final Path translogFile = location.resolve(getFilename(checkpoint.generation)); | ||
| try (TranslogReader reader = openReader(translogFile, checkpoint, expectedTranslogUUID)) { | ||
|
|
||
| try (FileChannel channel = FileChannel.open(translogFile, StandardOpenOption.READ)) { | ||
| TranslogHeader.read(expectedTranslogUUID, translogFile, channel); | ||
| } catch (TranslogCorruptedException ex) { | ||
| throw ex; // just bubble up. | ||
| } catch (Exception ex) { | ||
|
|
@@ -1723,7 +1728,7 @@ static String createEmptyTranslog(Path location, long initialGlobalCheckpoint, S | |
| final String translogUUID = UUIDs.randomBase64UUID(); | ||
| TranslogWriter writer = TranslogWriter.create(shardId, translogUUID, 1, location.resolve(getFilename(1)), channelFactory, | ||
| new ByteSizeValue(10), 1, initialGlobalCheckpoint, | ||
| () -> { throw new UnsupportedOperationException(); }, () -> { throw new UnsupportedOperationException(); } | ||
| () -> { throw new UnsupportedOperationException(); }, () -> { throw new UnsupportedOperationException(); }, 0L | ||
|
||
| ); | ||
| writer.close(); | ||
| return translogUUID; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add java docs for the term supplier ? also describe what the term means here - i.e., it is sampled when a generation is rolled and the translog will reject operations with a higher term until rolled again.