|
@@ -1050,21 +1050,6 @@ public class BlockManager {
|
|
|
|
|
|
node.resetBlocks();
|
|
|
invalidateBlocks.remove(node);
|
|
|
-
|
|
|
- // If the DN hasn't block-reported since the most recent
|
|
|
- // failover, then we may have been holding up on processing
|
|
|
- // over-replicated blocks because of it. But we can now
|
|
|
- // process those blocks.
|
|
|
- boolean stale = false;
|
|
|
- for(DatanodeStorageInfo storage : node.getStorageInfos()) {
|
|
|
- if (storage.areBlockContentsStale()) {
|
|
|
- stale = true;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (stale) {
|
|
|
- rescanPostponedMisreplicatedBlocks();
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
/** Remove the blocks associated to the given DatanodeStorageInfo. */
|
|
@@ -1818,17 +1803,7 @@ public class BlockManager {
|
|
|
invalidatedBlocks = processReport(storageInfo, newReport);
|
|
|
}
|
|
|
|
|
|
- // Now that we have an up-to-date block report, we know that any
|
|
|
- // deletions from a previous NN iteration have been accounted for.
|
|
|
- boolean staleBefore = storageInfo.areBlockContentsStale();
|
|
|
storageInfo.receivedBlockReport();
|
|
|
- if (staleBefore && !storageInfo.areBlockContentsStale()) {
|
|
|
- LOG.info("BLOCK* processReport: Received first block report from "
|
|
|
- + storage + " after starting up or becoming active. Its block "
|
|
|
- + "contents are no longer considered stale");
|
|
|
- rescanPostponedMisreplicatedBlocks();
|
|
|
- }
|
|
|
-
|
|
|
} finally {
|
|
|
endTime = Time.now();
|
|
|
namesystem.writeUnlock();
|
|
@@ -1857,31 +1832,74 @@ public class BlockManager {
|
|
|
/**
|
|
|
* Rescan the list of blocks which were previously postponed.
|
|
|
*/
|
|
|
- private void rescanPostponedMisreplicatedBlocks() {
|
|
|
- for (Iterator<Block> it = postponedMisreplicatedBlocks.iterator();
|
|
|
- it.hasNext();) {
|
|
|
- Block b = it.next();
|
|
|
-
|
|
|
- BlockInfo bi = blocksMap.getStoredBlock(b);
|
|
|
- if (bi == null) {
|
|
|
- if (LOG.isDebugEnabled()) {
|
|
|
- LOG.debug("BLOCK* rescanPostponedMisreplicatedBlocks: " +
|
|
|
- "Postponed mis-replicated block " + b + " no longer found " +
|
|
|
- "in block map.");
|
|
|
+ void rescanPostponedMisreplicatedBlocks() {
|
|
|
+ if (getPostponedMisreplicatedBlocksCount() == 0) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ long startTimeRescanPostponedMisReplicatedBlocks = Time.now();
|
|
|
+ long startPostponedMisReplicatedBlocksCount =
|
|
|
+ getPostponedMisreplicatedBlocksCount();
|
|
|
+ namesystem.writeLock();
|
|
|
+ try {
|
|
|
+ // blocksPerRescan is the configured number of blocks per rescan.
|
|
|
+ // Randomly select blocksPerRescan consecutive blocks from the HashSet
|
|
|
+ // when the number of blocks remaining is larger than blocksPerRescan.
|
|
|
+ // The reason we don't always pick the first blocksPerRescan blocks is to
|
|
|
+ // handle the case if for some reason some datanodes remain in
|
|
|
+ // content stale state for a long time and only impact the first
|
|
|
+ // blocksPerRescan blocks.
|
|
|
+ int i = 0;
|
|
|
+ long startIndex = 0;
|
|
|
+ long blocksPerRescan =
|
|
|
+ datanodeManager.getBlocksPerPostponedMisreplicatedBlocksRescan();
|
|
|
+ long base = getPostponedMisreplicatedBlocksCount() - blocksPerRescan;
|
|
|
+ if (base > 0) {
|
|
|
+ startIndex = DFSUtil.getRandom().nextLong() % (base+1);
|
|
|
+ if (startIndex < 0) {
|
|
|
+ startIndex += (base+1);
|
|
|
}
|
|
|
- it.remove();
|
|
|
- postponedMisreplicatedBlocksCount.decrementAndGet();
|
|
|
- continue;
|
|
|
}
|
|
|
- MisReplicationResult res = processMisReplicatedBlock(bi);
|
|
|
- if (LOG.isDebugEnabled()) {
|
|
|
- LOG.debug("BLOCK* rescanPostponedMisreplicatedBlocks: " +
|
|
|
- "Re-scanned block " + b + ", result is " + res);
|
|
|
+ Iterator<Block> it = postponedMisreplicatedBlocks.iterator();
|
|
|
+ for (int tmp = 0; tmp < startIndex; tmp++) {
|
|
|
+ it.next();
|
|
|
}
|
|
|
- if (res != MisReplicationResult.POSTPONE) {
|
|
|
- it.remove();
|
|
|
- postponedMisreplicatedBlocksCount.decrementAndGet();
|
|
|
+
|
|
|
+ for (;it.hasNext(); i++) {
|
|
|
+ Block b = it.next();
|
|
|
+ if (i >= blocksPerRescan) {
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ BlockInfo bi = blocksMap.getStoredBlock(b);
|
|
|
+ if (bi == null) {
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("BLOCK* rescanPostponedMisreplicatedBlocks: " +
|
|
|
+ "Postponed mis-replicated block " + b + " no longer found " +
|
|
|
+ "in block map.");
|
|
|
+ }
|
|
|
+ it.remove();
|
|
|
+ postponedMisreplicatedBlocksCount.decrementAndGet();
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ MisReplicationResult res = processMisReplicatedBlock(bi);
|
|
|
+ if (LOG.isDebugEnabled()) {
|
|
|
+ LOG.debug("BLOCK* rescanPostponedMisreplicatedBlocks: " +
|
|
|
+ "Re-scanned block " + b + ", result is " + res);
|
|
|
+ }
|
|
|
+ if (res != MisReplicationResult.POSTPONE) {
|
|
|
+ it.remove();
|
|
|
+ postponedMisreplicatedBlocksCount.decrementAndGet();
|
|
|
+ }
|
|
|
}
|
|
|
+ } finally {
|
|
|
+ namesystem.writeUnlock();
|
|
|
+ long endPostponedMisReplicatedBlocksCount =
|
|
|
+ getPostponedMisreplicatedBlocksCount();
|
|
|
+ LOG.info("Rescan of postponedMisreplicatedBlocks completed in " +
|
|
|
+ (Time.now() - startTimeRescanPostponedMisReplicatedBlocks) +
|
|
|
+ " msecs. " + endPostponedMisReplicatedBlocksCount +
|
|
|
+ " blocks are left. " + (startPostponedMisReplicatedBlocksCount -
|
|
|
+ endPostponedMisReplicatedBlocksCount) + " blocks are removed.");
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -3580,6 +3598,7 @@ public class BlockManager {
|
|
|
if (namesystem.isPopulatingReplQueues()) {
|
|
|
computeDatanodeWork();
|
|
|
processPendingReplications();
|
|
|
+ rescanPostponedMisreplicatedBlocks();
|
|
|
}
|
|
|
Thread.sleep(replicationRecheckInterval);
|
|
|
} catch (Throwable t) {
|
|
@@ -3648,6 +3667,8 @@ public class BlockManager {
|
|
|
excessReplicateMap.clear();
|
|
|
invalidateBlocks.clear();
|
|
|
datanodeManager.clearPendingQueues();
|
|
|
+ postponedMisreplicatedBlocks.clear();
|
|
|
+ postponedMisreplicatedBlocksCount.set(0);
|
|
|
};
|
|
|
|
|
|
|