|
@@ -1,143 +0,0 @@
|
|
|
-/**
|
|
|
- * 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.hadoop.hdfs.server.blockmanagement;
|
|
|
-
|
|
|
-import com.google.common.annotations.VisibleForTesting;
|
|
|
-import org.apache.hadoop.hdfs.util.LightWeightHashSet;
|
|
|
-import org.apache.hadoop.util.Time;
|
|
|
-import org.slf4j.Logger;
|
|
|
-
|
|
|
-import java.util.concurrent.TimeUnit;
|
|
|
-
|
|
|
-/**
|
|
|
- * PendingRecoveryBlocks tracks recovery attempts for each block and their
|
|
|
- * timeouts to ensure we do not have multiple recoveries at the same time
|
|
|
- * and retry only after the timeout for a recovery has expired.
|
|
|
- */
|
|
|
-class PendingRecoveryBlocks {
|
|
|
- private static final Logger LOG = BlockManager.LOG;
|
|
|
-
|
|
|
- /** List of recovery attempts per block and the time they expire. */
|
|
|
- private final LightWeightHashSet<BlockRecoveryAttempt> recoveryTimeouts =
|
|
|
- new LightWeightHashSet<>();
|
|
|
-
|
|
|
- /** The timeout for issuing a block recovery again.
|
|
|
- * (it should be larger than the time to recover a block)
|
|
|
- */
|
|
|
- private long recoveryTimeoutInterval;
|
|
|
-
|
|
|
- PendingRecoveryBlocks(long timeout) {
|
|
|
- this.recoveryTimeoutInterval = timeout;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Remove recovery attempt for the given block.
|
|
|
- * @param block whose recovery attempt to remove.
|
|
|
- */
|
|
|
- synchronized void remove(BlockInfo block) {
|
|
|
- recoveryTimeouts.remove(new BlockRecoveryAttempt(block));
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Checks whether a recovery attempt has been made for the given block.
|
|
|
- * If so, checks whether that attempt has timed out.
|
|
|
- * @param block block for which recovery is being attempted
|
|
|
- * @return true if no recovery attempt has been made or
|
|
|
- * the previous attempt timed out
|
|
|
- */
|
|
|
- synchronized boolean add(BlockInfo block) {
|
|
|
- boolean added = false;
|
|
|
- long curTime = getTime();
|
|
|
- BlockRecoveryAttempt recoveryAttempt =
|
|
|
- recoveryTimeouts.getElement(new BlockRecoveryAttempt(block));
|
|
|
-
|
|
|
- if (recoveryAttempt == null) {
|
|
|
- BlockRecoveryAttempt newAttempt = new BlockRecoveryAttempt(
|
|
|
- block, curTime + recoveryTimeoutInterval);
|
|
|
- added = recoveryTimeouts.add(newAttempt);
|
|
|
- } else if (recoveryAttempt.hasTimedOut(curTime)) {
|
|
|
- // Previous attempt timed out, reset the timeout
|
|
|
- recoveryAttempt.setTimeout(curTime + recoveryTimeoutInterval);
|
|
|
- added = true;
|
|
|
- } else {
|
|
|
- long timeoutIn = TimeUnit.MILLISECONDS.toSeconds(
|
|
|
- recoveryAttempt.timeoutAt - curTime);
|
|
|
- LOG.info("Block recovery attempt for " + block + " rejected, as the " +
|
|
|
- "previous attempt times out in " + timeoutIn + " seconds.");
|
|
|
- }
|
|
|
- return added;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Check whether the given block is under recovery.
|
|
|
- * @param b block for which to check
|
|
|
- * @return true if the given block is being recovered
|
|
|
- */
|
|
|
- synchronized boolean isUnderRecovery(BlockInfo b) {
|
|
|
- BlockRecoveryAttempt recoveryAttempt =
|
|
|
- recoveryTimeouts.getElement(new BlockRecoveryAttempt(b));
|
|
|
- return recoveryAttempt != null;
|
|
|
- }
|
|
|
-
|
|
|
- long getTime() {
|
|
|
- return Time.monotonicNow();
|
|
|
- }
|
|
|
-
|
|
|
- @VisibleForTesting
|
|
|
- synchronized void setRecoveryTimeoutInterval(long recoveryTimeoutInterval) {
|
|
|
- this.recoveryTimeoutInterval = recoveryTimeoutInterval;
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Tracks timeout for block recovery attempt of a given block.
|
|
|
- */
|
|
|
- private static class BlockRecoveryAttempt {
|
|
|
- private final BlockInfo blockInfo;
|
|
|
- private long timeoutAt;
|
|
|
-
|
|
|
- private BlockRecoveryAttempt(BlockInfo blockInfo) {
|
|
|
- this(blockInfo, 0);
|
|
|
- }
|
|
|
-
|
|
|
- BlockRecoveryAttempt(BlockInfo blockInfo, long timeoutAt) {
|
|
|
- this.blockInfo = blockInfo;
|
|
|
- this.timeoutAt = timeoutAt;
|
|
|
- }
|
|
|
-
|
|
|
- boolean hasTimedOut(long currentTime) {
|
|
|
- return currentTime > timeoutAt;
|
|
|
- }
|
|
|
-
|
|
|
- void setTimeout(long newTimeoutAt) {
|
|
|
- this.timeoutAt = newTimeoutAt;
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public int hashCode() {
|
|
|
- return blockInfo.hashCode();
|
|
|
- }
|
|
|
-
|
|
|
- @Override
|
|
|
- public boolean equals(Object obj) {
|
|
|
- if (obj instanceof BlockRecoveryAttempt) {
|
|
|
- return this.blockInfo.equals(((BlockRecoveryAttempt) obj).blockInfo);
|
|
|
- }
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
-}
|