|
@@ -105,6 +105,7 @@ class BlockPoolSliceScanner {
|
|
private long bytesLeft = 0; // Bytes to scan in this period
|
|
private long bytesLeft = 0; // Bytes to scan in this period
|
|
private long totalBytesToScan = 0;
|
|
private long totalBytesToScan = 0;
|
|
private boolean isNewPeriod = true;
|
|
private boolean isNewPeriod = true;
|
|
|
|
+ private int lastScanTimeDifference = 5*60*1000;
|
|
|
|
|
|
private final LogFileHandler verificationLog;
|
|
private final LogFileHandler verificationLog;
|
|
|
|
|
|
@@ -112,6 +113,7 @@ class BlockPoolSliceScanner {
|
|
200, MAX_SCAN_RATE);
|
|
200, MAX_SCAN_RATE);
|
|
|
|
|
|
private static enum ScanType {
|
|
private static enum ScanType {
|
|
|
|
+ IMMEDIATE_SCAN,
|
|
VERIFICATION_SCAN, // scanned as part of periodic verfication
|
|
VERIFICATION_SCAN, // scanned as part of periodic verfication
|
|
NONE,
|
|
NONE,
|
|
}
|
|
}
|
|
@@ -129,12 +131,17 @@ class BlockPoolSliceScanner {
|
|
|
|
|
|
@Override
|
|
@Override
|
|
public int compare(BlockScanInfo left, BlockScanInfo right) {
|
|
public int compare(BlockScanInfo left, BlockScanInfo right) {
|
|
|
|
+ final ScanType leftNextScanType = left.nextScanType;
|
|
|
|
+ final ScanType rightNextScanType = right.nextScanType;
|
|
final long l = left.lastScanTime;
|
|
final long l = left.lastScanTime;
|
|
final long r = right.lastScanTime;
|
|
final long r = right.lastScanTime;
|
|
|
|
+ // Compare by nextScanType if they are same then compare by
|
|
|
|
+ // lastScanTimes
|
|
// compare blocks itself if scantimes are same to avoid.
|
|
// compare blocks itself if scantimes are same to avoid.
|
|
// because TreeMap uses comparator if available to check existence of
|
|
// because TreeMap uses comparator if available to check existence of
|
|
// the object.
|
|
// the object.
|
|
- return l < r? -1: l > r? 1: left.compareTo(right);
|
|
|
|
|
|
+ int compareByNextScanType = leftNextScanType.compareTo(rightNextScanType);
|
|
|
|
+ return compareByNextScanType < 0? -1: compareByNextScanType > 0? 1: l < r? -1: l > r? 1: left.compareTo(right);
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
@@ -142,6 +149,7 @@ class BlockPoolSliceScanner {
|
|
ScanType lastScanType = ScanType.NONE;
|
|
ScanType lastScanType = ScanType.NONE;
|
|
boolean lastScanOk = true;
|
|
boolean lastScanOk = true;
|
|
private LinkedElement next;
|
|
private LinkedElement next;
|
|
|
|
+ ScanType nextScanType = ScanType.VERIFICATION_SCAN;
|
|
|
|
|
|
BlockScanInfo(Block block) {
|
|
BlockScanInfo(Block block) {
|
|
super(block);
|
|
super(block);
|
|
@@ -265,10 +273,12 @@ class BlockPoolSliceScanner {
|
|
private synchronized void updateBlockInfo(LogEntry e) {
|
|
private synchronized void updateBlockInfo(LogEntry e) {
|
|
BlockScanInfo info = blockMap.get(new Block(e.blockId, 0, e.genStamp));
|
|
BlockScanInfo info = blockMap.get(new Block(e.blockId, 0, e.genStamp));
|
|
|
|
|
|
- if(info != null && e.verificationTime > 0 &&
|
|
|
|
|
|
+ if (info != null && e.verificationTime > 0 &&
|
|
info.lastScanTime < e.verificationTime) {
|
|
info.lastScanTime < e.verificationTime) {
|
|
delBlockInfo(info);
|
|
delBlockInfo(info);
|
|
- info.lastScanTime = e.verificationTime;
|
|
|
|
|
|
+ if (info.nextScanType != ScanType.IMMEDIATE_SCAN) {
|
|
|
|
+ info.lastScanTime = e.verificationTime;
|
|
|
|
+ }
|
|
info.lastScanType = ScanType.VERIFICATION_SCAN;
|
|
info.lastScanType = ScanType.VERIFICATION_SCAN;
|
|
addBlockInfo(info, false);
|
|
addBlockInfo(info, false);
|
|
}
|
|
}
|
|
@@ -285,9 +295,23 @@ class BlockPoolSliceScanner {
|
|
DFSUtil.getRandom().nextInt(periodInt);
|
|
DFSUtil.getRandom().nextInt(periodInt);
|
|
}
|
|
}
|
|
|
|
|
|
- /** Adds block to list of blocks */
|
|
|
|
- synchronized void addBlock(ExtendedBlock block) {
|
|
|
|
|
|
+ /** Adds block to list of blocks
|
|
|
|
+ * @param scanNow - true if we want to make that particular block a high
|
|
|
|
+ * priority one to scan immediately
|
|
|
|
+ **/
|
|
|
|
+ synchronized void addBlock(ExtendedBlock block, boolean scanNow) {
|
|
BlockScanInfo info = blockMap.get(block.getLocalBlock());
|
|
BlockScanInfo info = blockMap.get(block.getLocalBlock());
|
|
|
|
+ long lastScanTime = 0;
|
|
|
|
+ if (info != null) {
|
|
|
|
+ lastScanTime = info.lastScanTime;
|
|
|
|
+ }
|
|
|
|
+ // If the particular block is scanned in last 5 minutes, the no need to
|
|
|
|
+ // verify that block again
|
|
|
|
+ if (scanNow && Time.monotonicNow() - lastScanTime <
|
|
|
|
+ lastScanTimeDifference) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
if ( info != null ) {
|
|
if ( info != null ) {
|
|
LOG.warn("Adding an already existing block " + block);
|
|
LOG.warn("Adding an already existing block " + block);
|
|
delBlockInfo(info);
|
|
delBlockInfo(info);
|
|
@@ -295,6 +319,12 @@ class BlockPoolSliceScanner {
|
|
|
|
|
|
info = new BlockScanInfo(block.getLocalBlock());
|
|
info = new BlockScanInfo(block.getLocalBlock());
|
|
info.lastScanTime = getNewBlockScanTime();
|
|
info.lastScanTime = getNewBlockScanTime();
|
|
|
|
+ if (scanNow) {
|
|
|
|
+ // Create a new BlockScanInfo object and set the lastScanTime to 0
|
|
|
|
+ // which will make it the high priority block
|
|
|
|
+ LOG.info("Adding block for immediate verification " + block);
|
|
|
|
+ info.nextScanType = ScanType.IMMEDIATE_SCAN;
|
|
|
|
+ }
|
|
|
|
|
|
addBlockInfo(info, true);
|
|
addBlockInfo(info, true);
|
|
adjustThrottler();
|
|
adjustThrottler();
|
|
@@ -340,6 +370,7 @@ class BlockPoolSliceScanner {
|
|
info.lastScanType = type;
|
|
info.lastScanType = type;
|
|
info.lastScanTime = now;
|
|
info.lastScanTime = now;
|
|
info.lastScanOk = scanOk;
|
|
info.lastScanOk = scanOk;
|
|
|
|
+ info.nextScanType = ScanType.VERIFICATION_SCAN;
|
|
addBlockInfo(info, false);
|
|
addBlockInfo(info, false);
|
|
|
|
|
|
// Don't update meta data if the verification failed.
|
|
// Don't update meta data if the verification failed.
|
|
@@ -363,6 +394,11 @@ class BlockPoolSliceScanner {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ @VisibleForTesting
|
|
|
|
+ synchronized void setLastScanTimeDifference(int lastScanTimeDifference) {
|
|
|
|
+ this.lastScanTimeDifference = lastScanTimeDifference;
|
|
|
|
+ }
|
|
|
|
+
|
|
static private class LogEntry {
|
|
static private class LogEntry {
|
|
|
|
|
|
long blockId = -1;
|
|
long blockId = -1;
|
|
@@ -502,6 +538,9 @@ class BlockPoolSliceScanner {
|
|
|
|
|
|
private synchronized boolean isFirstBlockProcessed() {
|
|
private synchronized boolean isFirstBlockProcessed() {
|
|
if (!blockInfoSet.isEmpty()) {
|
|
if (!blockInfoSet.isEmpty()) {
|
|
|
|
+ if (blockInfoSet.first().nextScanType == ScanType.IMMEDIATE_SCAN) {
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
long blockId = blockInfoSet.first().getBlockId();
|
|
long blockId = blockInfoSet.first().getBlockId();
|
|
if ((processedBlocks.get(blockId) != null)
|
|
if ((processedBlocks.get(blockId) != null)
|
|
&& (processedBlocks.get(blockId) == 1)) {
|
|
&& (processedBlocks.get(blockId) == 1)) {
|