DFS-1257. Fix a race condition on BlockManager.recentInvalidateSets. Contributed by Eric Payne

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1158933 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Tsz-wo Sze 2011-08-17 22:00:27 +00:00
parent b094465168
commit cc875f0124
2 changed files with 83 additions and 58 deletions

View File

@ -972,6 +972,9 @@ Trunk (unreleased changes)
HDFS-73. DFSOutputStream does not close all the sockets.
(Uma Maheswara Rao G via eli)
HDFS-1257. Fix a race condition on BlockManager.recentInvalidateSets.
(Eric Payne via szetszwo)
BREAKDOWN OF HDFS-1073 SUBTASKS
HDFS-1521. Persist transaction ID on disk between NN restarts.

View File

@ -758,6 +758,7 @@ void removeBlocksAssociatedTo(final DatanodeDescriptor node) {
}
private void removeFromInvalidates(String storageID, Block block) {
synchronized(recentInvalidateSets) {
Collection<Block> v = recentInvalidateSets.get(storageID);
if (v != null && v.remove(block)) {
pendingDeletionBlocksCount--;
@ -766,11 +767,15 @@ private void removeFromInvalidates(String storageID, Block block) {
}
}
}
}
boolean belongsToInvalidates(String storageID, Block block) {
Collection<Block> invalidateSet = recentInvalidateSets.get(storageID);
Collection<Block> invalidateSet;
synchronized(recentInvalidateSets) {
invalidateSet = recentInvalidateSets.get(storageID);
return invalidateSet != null && invalidateSet.contains(block);
}
}
/**
* Adds block to list of blocks which will be invalidated on specified
@ -781,6 +786,7 @@ boolean belongsToInvalidates(String storageID, Block block) {
* @param log true to create an entry in the log
*/
private void addToInvalidates(Block b, DatanodeInfo dn, boolean log) {
synchronized(recentInvalidateSets) {
Collection<Block> invalidateSet = recentInvalidateSets
.get(dn.getStorageID());
if (invalidateSet == null) {
@ -795,6 +801,7 @@ private void addToInvalidates(Block b, DatanodeInfo dn, boolean log) {
}
}
}
}
/**
* Adds block to list of blocks which will be invalidated on specified
@ -830,12 +837,16 @@ private void addToInvalidates(Block b) {
*/
private void dumpRecentInvalidateSets(PrintWriter out) {
assert namesystem.hasWriteLock();
int size = recentInvalidateSets.values().size();
int size;
synchronized(recentInvalidateSets) {
size = recentInvalidateSets.values().size();
}
out.println("Metasave: Blocks " + pendingDeletionBlocksCount
+ " waiting deletion from " + size + " datanodes.");
if (size == 0) {
return;
}
synchronized(recentInvalidateSets) {
for(Map.Entry<String,Collection<Block>> entry : recentInvalidateSets.entrySet()) {
Collection<Block> blocks = entry.getValue();
if (blocks.size() > 0) {
@ -843,6 +854,7 @@ private void dumpRecentInvalidateSets(PrintWriter out) {
}
}
}
}
/**
* Mark the block belonging to datanode as corrupt
@ -950,13 +962,16 @@ public int getUnderReplicatedNotMissingBlocks() {
* @return total number of block for deletion
*/
int computeInvalidateWork(int nodesToProcess) {
int numOfNodes = recentInvalidateSets.size();
nodesToProcess = Math.min(numOfNodes, nodesToProcess);
int numOfNodes;
ArrayList<String> keyArray;
// TODO should using recentInvalidateSets be synchronized?
synchronized(recentInvalidateSets) {
numOfNodes = recentInvalidateSets.size();
// get an array of the keys
ArrayList<String> keyArray =
new ArrayList<String>(recentInvalidateSets.keySet());
keyArray = new ArrayList<String>(recentInvalidateSets.keySet());
}
nodesToProcess = Math.min(numOfNodes, nodesToProcess);
// randomly pick up <i>nodesToProcess</i> nodes
// and put them at [0, nodesToProcess)
@ -2428,7 +2443,10 @@ private int getReplication(Block block) {
/** Remove a datanode from the invalidatesSet */
private void removeFromInvalidates(String storageID) {
Collection<Block> blocks = recentInvalidateSets.remove(storageID);
Collection<Block> blocks;
synchronized(recentInvalidateSets) {
blocks = recentInvalidateSets.remove(storageID);
}
if (blocks != null) {
pendingDeletionBlocksCount -= blocks.size();
}
@ -2454,11 +2472,14 @@ private int invalidateWorkForOneNode(String nodeId) {
return 0;
}
Collection<Block> invalidateSet = recentInvalidateSets.get(nodeId);
Collection<Block> invalidateSet;
ArrayList<Block> blocksToInvalidate;
synchronized(recentInvalidateSets) {
invalidateSet = recentInvalidateSets.get(nodeId);
if (invalidateSet == null)
return 0;
ArrayList<Block> blocksToInvalidate = new ArrayList<Block>(
blocksToInvalidate = new ArrayList<Block>(
getDatanodeManager().blockInvalidateLimit);
// # blocks that can be sent in one message is limited
@ -2487,6 +2508,7 @@ private int invalidateWorkForOneNode(String nodeId) {
}
pendingDeletionBlocksCount -= blocksToInvalidate.size();
return blocksToInvalidate.size();
}
} finally {
namesystem.writeUnlock();
}