|
@@ -347,6 +347,10 @@ public class DecommissionManager {
|
|
|
* The number of blocks that have been checked on this tick.
|
|
|
*/
|
|
|
private int numBlocksChecked = 0;
|
|
|
+ /**
|
|
|
+ * The number of blocks checked after (re)holding lock.
|
|
|
+ */
|
|
|
+ private int numBlocksCheckedPerLock = 0;
|
|
|
/**
|
|
|
* The number of nodes that have been checked on this tick. Used for
|
|
|
* testing.
|
|
@@ -385,6 +389,7 @@ public class DecommissionManager {
|
|
|
}
|
|
|
// Reset the checked count at beginning of each iteration
|
|
|
numBlocksChecked = 0;
|
|
|
+ numBlocksCheckedPerLock = 0;
|
|
|
numNodesChecked = 0;
|
|
|
// Check decom progress
|
|
|
namesystem.writeLock();
|
|
@@ -417,9 +422,8 @@ public class DecommissionManager {
|
|
|
it = new CyclicIteration<>(decomNodeBlocks, iterkey).iterator();
|
|
|
final LinkedList<DatanodeDescriptor> toRemove = new LinkedList<>();
|
|
|
|
|
|
- while (it.hasNext()
|
|
|
- && !exceededNumBlocksPerCheck()
|
|
|
- && !exceededNumNodesPerCheck()) {
|
|
|
+ while (it.hasNext() && !exceededNumBlocksPerCheck()
|
|
|
+ && !exceededNumNodesPerCheck() && namesystem.isRunning()) {
|
|
|
numNodesChecked++;
|
|
|
final Map.Entry<DatanodeDescriptor, AbstractList<BlockInfoContiguous>>
|
|
|
entry = it.next();
|
|
@@ -544,7 +548,28 @@ public class DecommissionManager {
|
|
|
int decommissionOnlyReplicas = 0;
|
|
|
int underReplicatedInOpenFiles = 0;
|
|
|
while (it.hasNext()) {
|
|
|
+ if (insufficientlyReplicated == null
|
|
|
+ && numBlocksCheckedPerLock >= numBlocksPerCheck) {
|
|
|
+ // During fullscan insufficientlyReplicated will NOT be null, iterator
|
|
|
+ // will be DN's iterator. So should not yield lock, otherwise
|
|
|
+ // ConcurrentModificationException could occur.
|
|
|
+ // Once the fullscan done, iterator will be a copy. So can yield the
|
|
|
+ // lock.
|
|
|
+ // Yielding is required in case of block number is greater than the
|
|
|
+ // configured per-iteration-limit.
|
|
|
+ namesystem.writeUnlock();
|
|
|
+ try {
|
|
|
+ LOG.debug("Yielded lock during decommission check");
|
|
|
+ Thread.sleep(0, 500);
|
|
|
+ } catch (InterruptedException ignored) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //reset
|
|
|
+ numBlocksCheckedPerLock = 0;
|
|
|
+ namesystem.writeLock();
|
|
|
+ }
|
|
|
numBlocksChecked++;
|
|
|
+ numBlocksCheckedPerLock++;
|
|
|
final BlockInfoContiguous block = it.next();
|
|
|
// Remove the block from the list if it's no longer in the block map,
|
|
|
// e.g. the containing file has been deleted
|