All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.flink.streaming.runtime.io.checkpointing.CheckpointedInputGate Maven / Gradle / Ivy

There is a newer version: 1.14.6
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.flink.streaming.runtime.io.checkpointing;

import org.apache.flink.annotation.Internal;
import org.apache.flink.annotation.VisibleForTesting;
import org.apache.flink.api.common.operators.MailboxExecutor;
import org.apache.flink.runtime.checkpoint.channel.InputChannelInfo;
import org.apache.flink.runtime.event.AbstractEvent;
import org.apache.flink.runtime.io.PullingAsyncDataInput;
import org.apache.flink.runtime.io.network.api.CancelCheckpointMarker;
import org.apache.flink.runtime.io.network.api.CheckpointBarrier;
import org.apache.flink.runtime.io.network.api.EndOfData;
import org.apache.flink.runtime.io.network.api.EndOfPartitionEvent;
import org.apache.flink.runtime.io.network.api.EventAnnouncement;
import org.apache.flink.runtime.io.network.partition.consumer.BufferOrEvent;
import org.apache.flink.runtime.io.network.partition.consumer.EndOfChannelStateEvent;
import org.apache.flink.runtime.io.network.partition.consumer.InputChannel;
import org.apache.flink.runtime.io.network.partition.consumer.InputGate;
import org.apache.flink.streaming.runtime.io.StreamTaskNetworkInput;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.RejectedExecutionException;

import static org.apache.flink.util.Preconditions.checkState;
import static org.apache.flink.util.concurrent.FutureUtils.assertNoException;

/**
 * The {@link CheckpointedInputGate} uses {@link CheckpointBarrierHandler} to handle incoming {@link
 * CheckpointBarrier} from the {@link InputGate}.
 */
@Internal
public class CheckpointedInputGate implements PullingAsyncDataInput, Closeable {
    private static final Logger LOG = LoggerFactory.getLogger(CheckpointedInputGate.class);

    private final CheckpointBarrierHandler barrierHandler;

    private final UpstreamRecoveryTracker upstreamRecoveryTracker;

    /** The gate that the buffer draws its input from. */
    private final InputGate inputGate;

    private final MailboxExecutor mailboxExecutor;

    /** Indicate end of the input. */
    private boolean isFinished;

    /**
     * Creates a new checkpoint stream aligner.
     *
     * 

The aligner will allow only alignments that buffer up to the given number of bytes. When * that number is exceeded, it will stop the alignment and notify the task that the checkpoint * has been cancelled. * * @param inputGate The input gate to draw the buffers and events from. * @param barrierHandler Handler that controls which channels are blocked. */ public CheckpointedInputGate( InputGate inputGate, CheckpointBarrierHandler barrierHandler, MailboxExecutor mailboxExecutor) { this(inputGate, barrierHandler, mailboxExecutor, UpstreamRecoveryTracker.NO_OP); } public CheckpointedInputGate( InputGate inputGate, CheckpointBarrierHandler barrierHandler, MailboxExecutor mailboxExecutor, UpstreamRecoveryTracker upstreamRecoveryTracker) { this.inputGate = inputGate; this.barrierHandler = barrierHandler; this.mailboxExecutor = mailboxExecutor; this.upstreamRecoveryTracker = upstreamRecoveryTracker; waitForPriorityEvents(inputGate, mailboxExecutor); } /** * Eagerly pulls and processes all priority events. Must be called from task thread. * *

Basic assumption is that no priority event needs to be handled by the {@link * StreamTaskNetworkInput}. */ private void processPriorityEvents() throws IOException, InterruptedException { // check if the priority event is still not processed (could have been pulled before mail // was being executed) boolean hasPriorityEvent = inputGate.getPriorityEventAvailableFuture().isDone(); while (hasPriorityEvent) { // process as many priority events as possible final Optional bufferOrEventOpt = pollNext(); if (!bufferOrEventOpt.isPresent()) { break; } final BufferOrEvent bufferOrEvent = bufferOrEventOpt.get(); checkState(bufferOrEvent.hasPriority(), "Should only poll priority events"); hasPriorityEvent = bufferOrEvent.morePriorityEvents(); } // re-enqueue mail to process future priority events waitForPriorityEvents(inputGate, mailboxExecutor); } private void waitForPriorityEvents(InputGate inputGate, MailboxExecutor mailboxExecutor) { final CompletableFuture priorityEventAvailableFuture = inputGate.getPriorityEventAvailableFuture(); assertNoException( priorityEventAvailableFuture.thenRun( () -> { try { mailboxExecutor.execute( this::processPriorityEvents, "process priority event @ gate %s", inputGate); } catch (RejectedExecutionException ex) { LOG.debug( "Ignored RejectedExecutionException in CheckpointedInputGate.waitForPriorityEvents"); } })); } @Override public CompletableFuture getAvailableFuture() { return inputGate.getAvailableFuture(); } @Override public Optional pollNext() throws IOException, InterruptedException { Optional next = inputGate.pollNext(); if (!next.isPresent()) { return handleEmptyBuffer(); } BufferOrEvent bufferOrEvent = next.get(); if (bufferOrEvent.isEvent()) { return handleEvent(bufferOrEvent); } else if (bufferOrEvent.isBuffer()) { /** * https://issues.apache.org/jira/browse/FLINK-19537 This is not entirely true, as it's * ignoring the buffer/bytes accumulated in the record deserializers. If buffer is * processed here, it doesn't mean it was fully processed (so we can over estimate the * amount of processed bytes). On the other hand some records/bytes might be processed * without polling anything from this {@link CheckpointedInputGate} (underestimating the * amount of processed bytes). All in all this should have been calculated on the {@link * StreamTaskNetworkInput} level, where we have an access to the records deserializers. * However the current is on average accurate and it might be just good enough (at least * for the time being). */ barrierHandler.addProcessedBytes(bufferOrEvent.getBuffer().getSize()); } return next; } private Optional handleEvent(BufferOrEvent bufferOrEvent) throws IOException { Class eventClass = bufferOrEvent.getEvent().getClass(); if (eventClass == CheckpointBarrier.class) { CheckpointBarrier checkpointBarrier = (CheckpointBarrier) bufferOrEvent.getEvent(); barrierHandler.processBarrier(checkpointBarrier, bufferOrEvent.getChannelInfo(), false); } else if (eventClass == CancelCheckpointMarker.class) { barrierHandler.processCancellationBarrier( (CancelCheckpointMarker) bufferOrEvent.getEvent(), bufferOrEvent.getChannelInfo()); } else if (eventClass == EndOfData.class) { inputGate.acknowledgeAllRecordsProcessed(bufferOrEvent.getChannelInfo()); } else if (eventClass == EndOfPartitionEvent.class) { barrierHandler.processEndOfPartition(bufferOrEvent.getChannelInfo()); } else if (eventClass == EventAnnouncement.class) { EventAnnouncement eventAnnouncement = (EventAnnouncement) bufferOrEvent.getEvent(); AbstractEvent announcedEvent = eventAnnouncement.getAnnouncedEvent(); checkState( announcedEvent instanceof CheckpointBarrier, "Only CheckpointBarrier announcement are currently supported, but found [%s]", announcedEvent); CheckpointBarrier announcedBarrier = (CheckpointBarrier) announcedEvent; barrierHandler.processBarrierAnnouncement( announcedBarrier, eventAnnouncement.getSequenceNumber(), bufferOrEvent.getChannelInfo()); } else if (bufferOrEvent.getEvent().getClass() == EndOfChannelStateEvent.class) { upstreamRecoveryTracker.handleEndOfRecovery(bufferOrEvent.getChannelInfo()); } return Optional.of(bufferOrEvent); } public CompletableFuture getAllBarriersReceivedFuture(long checkpointId) { return barrierHandler.getAllBarriersReceivedFuture(checkpointId); } private Optional handleEmptyBuffer() { if (inputGate.isFinished()) { isFinished = true; } return Optional.empty(); } @Override public boolean isFinished() { return isFinished; } @Override public boolean hasReceivedEndOfData() { return inputGate.hasReceivedEndOfData(); } /** * Cleans up all internally held resources. * * @throws IOException Thrown if the cleanup of I/O resources failed. */ public void close() throws IOException { barrierHandler.close(); } // ------------------------------------------------------------------------ // Properties // ------------------------------------------------------------------------ /** * Gets the ID defining the current pending, or just completed, checkpoint. * * @return The ID of the pending of completed checkpoint. */ @VisibleForTesting long getLatestCheckpointId() { return barrierHandler.getLatestCheckpointId(); } /** * Gets the time that the latest alignment took, in nanoseconds. If there is currently an * alignment in progress, it will return the time spent in the current alignment so far. * * @return The duration in nanoseconds */ @VisibleForTesting long getAlignmentDurationNanos() { return barrierHandler.getAlignmentDurationNanos(); } /** * @return the time that elapsed, in nanoseconds, between the creation of the latest checkpoint * and the time when it's first {@link CheckpointBarrier} was received by this {@link * InputGate}. */ @VisibleForTesting long getCheckpointStartDelayNanos() { return barrierHandler.getCheckpointStartDelayNanos(); } /** @return number of underlying input channels. */ public int getNumberOfInputChannels() { return inputGate.getNumberOfInputChannels(); } // ------------------------------------------------------------------------ // Utilities // ------------------------------------------------------------------------ @Override public String toString() { return barrierHandler.toString(); } public InputChannel getChannel(int channelIndex) { return inputGate.getChannel(channelIndex); } public List getChannelInfos() { return inputGate.getChannelInfos(); } public boolean allChannelsRecovered() { return upstreamRecoveryTracker.allChannelsRecovered(); } @VisibleForTesting CheckpointBarrierHandler getCheckpointBarrierHandler() { return barrierHandler; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy