Skip to content

Commit 784ba03

Browse files
committed
HDFS-17904. Move traversing excessRedundancyMap outside the BM lock during processTimedOutExcessBlocks
1 parent f1567a1 commit 784ba03

File tree

2 files changed

+75
-33
lines changed

2 files changed

+75
-33
lines changed

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockManager.java

Lines changed: 52 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3113,42 +3113,30 @@ void processTimedOutExcessBlocks() {
31133113
if (excessRedundancyMap.size() == 0) {
31143114
return;
31153115
}
3116+
3117+
long now = Time.monotonicNow();
3118+
Map<String, List<ExcessBlockInfo>> pendingScanBlocks = getPendingScanBlocks(now);
3119+
if (pendingScanBlocks.isEmpty()) {
3120+
return;
3121+
}
3122+
31163123
// TODO: Change to readLock(FSNamesysteLockMode.BM) since invalidateBlocks is thread safe.
31173124
namesystem.writeLock(RwLockMode.BM);
3118-
long now = Time.monotonicNow();
3119-
int processed = 0;
3125+
String datanodeUuid = null;
3126+
BlockInfo blockInfo = null;
31203127
try {
3121-
Iterator<Map.Entry<String, LightWeightHashSet<Block>>> iter =
3122-
excessRedundancyMap.getExcessRedundancyMap().entrySet().iterator();
3123-
while (iter.hasNext() && processed < excessRedundancyTimeoutCheckLimit) {
3124-
Map.Entry<String, LightWeightHashSet<Block>> entry = iter.next();
3125-
String datanodeUuid = entry.getKey();
3126-
LightWeightHashSet<Block> blocks = entry.getValue();
3127-
// Sort blocks by timestamp in descending order.
3128-
List<ExcessBlockInfo> sortedBlocks = blocks.stream()
3129-
.filter(block -> block instanceof ExcessBlockInfo)
3130-
.map(block -> (ExcessBlockInfo) block)
3131-
.sorted(Comparator.comparingLong(ExcessBlockInfo::getTimeStamp))
3132-
.collect(Collectors.toList());
3133-
3134-
for (ExcessBlockInfo excessBlockInfo : sortedBlocks) {
3135-
if (processed >= excessRedundancyTimeoutCheckLimit) {
3136-
break;
3137-
}
3138-
3139-
processed++;
3140-
// If the datanode doesn't have any excess block that has exceeded the timeout,
3141-
// can exit this loop.
3142-
if (now <= excessBlockInfo.getTimeStamp() + excessRedundancyTimeout) {
3143-
break;
3144-
}
3145-
3146-
BlockInfo blockInfo = excessBlockInfo.getBlockInfo();
3147-
BlockInfo bi = blocksMap.getStoredBlock(blockInfo);
3148-
if (bi == null || bi.isDeleted()) {
3128+
for (Map.Entry<String, List<ExcessBlockInfo>> entry : pendingScanBlocks.entrySet()) {
3129+
for (ExcessBlockInfo excessBlockInfo : entry.getValue()) {
3130+
datanodeUuid = entry.getKey();
3131+
blockInfo = excessBlockInfo.getBlockInfo();
3132+
BlockInfo storedBlock = blocksMap.getStoredBlock(blockInfo);
3133+
Block storedExcessBlock =
3134+
excessRedundancyMap.getExcessBlockInfo(datanodeUuid, blockInfo);
3135+
if (storedBlock == null || storedBlock.isDeleted()
3136+
|| !(storedExcessBlock instanceof ExcessBlockInfo)) {
31493137
continue;
31503138
}
3151-
3139+
blockInfo = ((ExcessBlockInfo) storedExcessBlock).getBlockInfo();
31523140
Iterator<DatanodeStorageInfo> iterator = blockInfo.getStorageInfos();
31533141
while (iterator.hasNext()) {
31543142
DatanodeStorageInfo datanodeStorageInfo = iterator.next();
@@ -3167,11 +3155,44 @@ void processTimedOutExcessBlocks() {
31673155
}
31683156
}
31693157
}
3158+
} catch (Throwable e) {
3159+
LOG.error("Fail to process excess block {} for {}.", blockInfo, datanodeUuid, e);
31703160
} finally {
31713161
namesystem.writeUnlock(RwLockMode.BM, "processTimedOutExcessBlocks");
31723162
LOG.info("processTimedOutExcessBlocks {} msecs.", (Time.monotonicNow() - now));
31733163
}
31743164
}
3165+
3166+
private Map<String, List<ExcessBlockInfo>> getPendingScanBlocks(long now) {
3167+
int processed = 0;
3168+
Map<String, List<ExcessBlockInfo>> pendingScanBlocks = new HashMap<>();
3169+
for (String dnUUID : excessRedundancyMap.getExcessDNs()) {
3170+
ArrayList<Block> excessBlocks = excessRedundancyMap.getExcessBlocks(dnUUID);
3171+
if (excessBlocks == null || excessBlocks.isEmpty()) {
3172+
continue;
3173+
}
3174+
List<ExcessBlockInfo> sortedBlocks = excessBlocks.stream()
3175+
.filter(block -> block instanceof ExcessBlockInfo)
3176+
.map(block -> (ExcessBlockInfo) block)
3177+
.sorted(Comparator.comparingLong(ExcessBlockInfo::getTimeStamp))
3178+
.collect(Collectors.toList());
3179+
for (ExcessBlockInfo block : sortedBlocks) {
3180+
if (processed >= excessRedundancyTimeoutCheckLimit) {
3181+
return pendingScanBlocks; // or break outer loop if you need to continue elsewhere
3182+
}
3183+
3184+
processed++;
3185+
if (now <= block.getTimeStamp() + excessRedundancyTimeout) {
3186+
// Since the list is sorted, no further block will be expired
3187+
break;
3188+
}
3189+
pendingScanBlocks
3190+
.computeIfAbsent(dnUUID, k -> new ArrayList<>())
3191+
.add(block);
3192+
}
3193+
}
3194+
return pendingScanBlocks;
3195+
}
31753196

31763197
Collection<Block> processReport(
31773198
final DatanodeStorageInfo storageInfo,

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/ExcessRedundancyMap.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818
package org.apache.hadoop.hdfs.server.blockmanagement;
1919

20+
import java.util.ArrayList;
2021
import java.util.HashMap;
2122
import java.util.Map;
2223
import java.util.concurrent.atomic.AtomicLong;
@@ -114,8 +115,28 @@ synchronized boolean remove(DatanodeDescriptor dn, BlockInfo blk) {
114115
return removed;
115116
}
116117

117-
synchronized Map<String, LightWeightHashSet<Block>> getExcessRedundancyMap() {
118-
return map;
118+
ArrayList<String> getExcessDNs() {
119+
return new ArrayList<>(map.keySet());
120+
}
121+
122+
ArrayList<Block> getExcessBlocks(String dnUUID) {
123+
final LightWeightHashSet<Block> set = map.get(dnUUID);
124+
if (set == null) {
125+
return null;
126+
}
127+
synchronized (set) {
128+
return new ArrayList<>(set);
129+
}
130+
}
131+
132+
Block getExcessBlockInfo(String dnUUId, BlockInfo blk) {
133+
final LightWeightHashSet<Block> set = map.get(dnUUId);
134+
if (set == null) {
135+
return null;
136+
}
137+
synchronized (set) {
138+
return set.getElement(blk);
139+
}
119140
}
120141

121142
/**

0 commit comments

Comments
 (0)