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

org.apache.flink.runtime.checkpoint.CheckpointStatsHistory Maven / Gradle / Ivy

There is a newer version: 1.13.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.runtime.checkpoint;

import javax.annotation.Nullable;

import java.io.Serializable;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.apache.flink.util.Preconditions.checkArgument;
import static org.apache.flink.util.Preconditions.checkNotNull;

/**
 * An array based history of checkpoint stats.
 *
 * 

The size of the array is constrained by the maximum allowed size. The * array starts empty an grows with each added checkpoint until it reaches * the maximum number of elements. At this point, the elements wrap around * and the least recently added entry is overwritten. * *

Access happens via checkpointsHistory over the statistics and a map that * exposes the checkpoint by their ID. Both of these are only guaranteed * to reflect the latest state after a call to {@link #createSnapshot()}. * *

Furthermore the history tracks the latest completed and latest failed * checkpoint as well as the latest savepoint. */ public class CheckpointStatsHistory implements Serializable { private static final long serialVersionUID = 7090320677606528415L; /** List over all available stats. Only updated on {@link #createSnapshot()}. */ private final List checkpointsHistory; /** Map of all available stats keyed by their ID. Only updated on {@link #createSnapshot()}. */ private final Map checkpointsById; /** Maximum array size. */ private final int maxSize; /** Flag indicating whether this the history is read-only. */ private final boolean readOnly; /** Array of checkpointsArray. Writes go against this array. */ private transient AbstractCheckpointStats[] checkpointsArray; /** Next position in {@link #checkpointsArray} to write to. */ private transient int nextPos; /** The latest successfully completed checkpoint. */ @Nullable private CompletedCheckpointStats latestCompletedCheckpoint; /** The latest failed checkpoint. */ @Nullable private FailedCheckpointStats latestFailedCheckpoint; /** The latest successfully completed savepoint. */ @Nullable private CompletedCheckpointStats latestSavepoint; /** * Creates a writeable checkpoint history with the given maximum size. * *

The read views are only updated on calls to {@link #createSnapshot()}. * Initially they are empty. * * @param maxSize Maximum history size. */ CheckpointStatsHistory(int maxSize) { this( false, maxSize, new AbstractCheckpointStats[0], Collections.emptyList(), Collections.emptyMap(), null, null, null); } /** * Creates a checkpoint history with the given maximum size and state. * *

The read views are only updated on calls to {@link #createSnapshot()}. * Initially they are empty. * * @param readOnly Flag indicating whether the history is read-only. * @param maxSize Maximum history size. * @param checkpointsHistory Checkpoints iterable. * @param checkpointsById Checkpoints by ID. */ private CheckpointStatsHistory( boolean readOnly, int maxSize, AbstractCheckpointStats[] checkpointArray, List checkpointsHistory, Map checkpointsById, CompletedCheckpointStats latestCompletedCheckpoint, FailedCheckpointStats latestFailedCheckpoint, CompletedCheckpointStats latestSavepoint) { this.readOnly = readOnly; checkArgument(maxSize >= 0, "Negative maximum size"); this.maxSize = maxSize; this.checkpointsArray = checkpointArray; this.checkpointsHistory = checkNotNull(checkpointsHistory); this.checkpointsById = checkNotNull(checkpointsById); this.latestCompletedCheckpoint = latestCompletedCheckpoint; this.latestFailedCheckpoint = latestFailedCheckpoint; this.latestSavepoint = latestSavepoint; } public List getCheckpoints() { return checkpointsHistory; } public AbstractCheckpointStats getCheckpointById(long checkpointId) { return checkpointsById.get(checkpointId); } @Nullable public CompletedCheckpointStats getLatestCompletedCheckpoint() { return latestCompletedCheckpoint; } @Nullable public FailedCheckpointStats getLatestFailedCheckpoint() { return latestFailedCheckpoint; } @Nullable public CompletedCheckpointStats getLatestSavepoint() { return latestSavepoint; } /** * Creates a snapshot of the current state. * * @return Snapshot of the current state. */ CheckpointStatsHistory createSnapshot() { if (readOnly) { throw new UnsupportedOperationException("Can't create a snapshot of a read-only history."); } List checkpointsHistory; Map checkpointsById; checkpointsById = new HashMap<>(checkpointsArray.length); if (maxSize == 0) { checkpointsHistory = Collections.emptyList(); } else { AbstractCheckpointStats[] newCheckpointsArray = new AbstractCheckpointStats[checkpointsArray.length]; System.arraycopy(checkpointsArray, nextPos, newCheckpointsArray, 0, checkpointsArray.length - nextPos); System.arraycopy(checkpointsArray, 0, newCheckpointsArray, checkpointsArray.length - nextPos, nextPos); checkpointsHistory = Arrays.asList(newCheckpointsArray); // reverse the order such that we start with the youngest checkpoint Collections.reverse(checkpointsHistory); for (AbstractCheckpointStats checkpoint : checkpointsHistory) { checkpointsById.put(checkpoint.getCheckpointId(), checkpoint); } } if (latestCompletedCheckpoint != null) { checkpointsById.put(latestCompletedCheckpoint.getCheckpointId(), latestCompletedCheckpoint); } if (latestFailedCheckpoint != null) { checkpointsById.put(latestFailedCheckpoint.getCheckpointId(), latestFailedCheckpoint); } if (latestSavepoint != null) { checkpointsById.put(latestSavepoint.getCheckpointId(), latestSavepoint); } return new CheckpointStatsHistory( true, maxSize, null, checkpointsHistory, checkpointsById, latestCompletedCheckpoint, latestFailedCheckpoint, latestSavepoint); } /** * Adds an in progress checkpoint to the checkpoint history. * * @param pending In progress checkpoint to add. */ void addInProgressCheckpoint(PendingCheckpointStats pending) { if (readOnly) { throw new UnsupportedOperationException("Can't create a snapshot of a read-only history."); } if (maxSize == 0) { return; } checkNotNull(pending, "Pending checkpoint"); // Grow the array if required. This happens only for the first entries // and makes the iterator logic easier, because we don't have any // null elements with the growing array. if (checkpointsArray.length < maxSize) { checkpointsArray = Arrays.copyOf(checkpointsArray, checkpointsArray.length + 1); } // Wrap around if we are at the end. The next pos is the least recently // added checkpoint. if (nextPos == checkpointsArray.length) { nextPos = 0; } checkpointsArray[nextPos++] = pending; } /** * Searches for the in progress checkpoint with the given ID and replaces * it with the given completed or failed checkpoint. * *

This is bounded by the maximum number of concurrent in progress * checkpointsArray, which means that the runtime of this is constant. * * @param completedOrFailed The completed or failed checkpoint to replace the in progress checkpoint with. * @return true if the checkpoint was replaced or false otherwise. */ boolean replacePendingCheckpointById(AbstractCheckpointStats completedOrFailed) { checkArgument(!completedOrFailed.getStatus().isInProgress(), "Not allowed to replace with in progress checkpoints."); if (readOnly) { throw new UnsupportedOperationException("Can't create a snapshot of a read-only history."); } // Update the latest checkpoint stats if (completedOrFailed.getStatus().isCompleted()) { CompletedCheckpointStats completed = (CompletedCheckpointStats) completedOrFailed; if (completed.getProperties().isSavepoint() && (latestSavepoint == null || completed.getCheckpointId() > latestSavepoint.getCheckpointId())) { latestSavepoint = completed; } else if (latestCompletedCheckpoint == null || completed.getCheckpointId() > latestCompletedCheckpoint.getCheckpointId()) { latestCompletedCheckpoint = completed; } } else if (completedOrFailed.getStatus().isFailed()) { FailedCheckpointStats failed = (FailedCheckpointStats) completedOrFailed; if (latestFailedCheckpoint == null || failed.getCheckpointId() > latestFailedCheckpoint.getCheckpointId()) { latestFailedCheckpoint = failed; } } if (maxSize == 0) { return false; } long checkpointId = completedOrFailed.getCheckpointId(); // We start searching from the last inserted position. Since the entries // wrap around the array we search until we are at index 0 and then from // the end of the array until (start pos + 1). int startPos = nextPos == checkpointsArray.length ? checkpointsArray.length - 1 : nextPos - 1; for (int i = startPos; i >= 0; i--) { if (checkpointsArray[i].getCheckpointId() == checkpointId) { checkpointsArray[i] = completedOrFailed; return true; } } for (int i = checkpointsArray.length - 1; i > startPos; i--) { if (checkpointsArray[i].getCheckpointId() == checkpointId) { checkpointsArray[i] = completedOrFailed; return true; } } return false; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy