Skip to content

Commit fc86756

Browse files
committed
HDFS-511. Remove redundant block searches in BlockManager. Contributed by Konstantin Shvachko.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/hdfs/trunk@799695 13f79535-47bb-0310-9956-ffa450edef68
1 parent 89f9717 commit fc86756

File tree

4 files changed

+76
-80
lines changed

4 files changed

+76
-80
lines changed

CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ Trunk (unreleased changes)
6565

6666
HDFS-496. Use PureJavaCrc32 in HDFS. (Todd Lipcon via szetszwo)
6767

68+
HDFS-511. Remove redundant block searches in BlockManager. (shv)
69+
6870
BUG FIXES
6971
HDFS-76. Better error message to users when commands fail because of
7072
lack of quota. Allow quota to be set even if the limit is lower than

src/java/org/apache/hadoop/hdfs/server/namenode/BlockManager.java

Lines changed: 71 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,7 @@ boolean checkMinReplication(Block block) {
233233
/**
234234
* Get all valid locations of the block
235235
*/
236-
ArrayList<String> addBlock(Block block) {
236+
ArrayList<String> getValidLocations(Block block) {
237237
ArrayList<String> machineSet =
238238
new ArrayList<String>(blocksMap.numNodes(block));
239239
for(Iterator<DatanodeDescriptor> it =
@@ -248,7 +248,6 @@ ArrayList<String> addBlock(Block block) {
248248
return machineSet;
249249
}
250250

251-
252251
List<LocatedBlock> getBlockLocations(Block[] blocks, long offset,
253252
long length, int nrBlocksToReturn) throws IOException {
254253
int curBlk = 0;
@@ -396,43 +395,50 @@ private void dumpRecentInvalidateSets(PrintWriter out) {
396395
}
397396
}
398397

399-
void markBlockAsCorrupt(Block blk, DatanodeInfo dn) throws IOException {
398+
void findAndMarkBlockAsCorrupt(Block blk,
399+
DatanodeInfo dn) throws IOException {
400+
BlockInfo storedBlock = getStoredBlock(blk);
401+
if (storedBlock == null) {
402+
// Check if the replica is in the blockMap, if not
403+
// ignore the request for now. This could happen when BlockScanner
404+
// thread of Datanode reports bad block before Block reports are sent
405+
// by the Datanode on startup
406+
NameNode.stateChangeLog.info("BLOCK* NameSystem.markBlockAsCorrupt: " +
407+
"block " + blk + " could not be marked as " +
408+
"corrupt as it does not exist in blocksMap");
409+
return;
410+
}
411+
markBlockAsCorrupt(storedBlock, dn);
412+
}
413+
414+
private void markBlockAsCorrupt(BlockInfo storedBlock,
415+
DatanodeInfo dn) throws IOException {
416+
assert storedBlock != null : "storedBlock should not be null";
400417
DatanodeDescriptor node = namesystem.getDatanode(dn);
401418
if (node == null) {
402-
throw new IOException("Cannot mark block" + blk.getBlockName() +
419+
throw new IOException("Cannot mark block " +
420+
storedBlock.getBlockName() +
403421
" as corrupt because datanode " + dn.getName() +
404422
" does not exist. ");
405423
}
406424

407-
final BlockInfo storedBlockInfo = blocksMap.getStoredBlock(blk);
408-
if (storedBlockInfo == null) {
409-
// Check if the replica is in the blockMap, if not
410-
// ignore the request for now. This could happen when BlockScanner
411-
// thread of Datanode reports bad block before Block reports are sent
412-
// by the Datanode on startup
425+
INodeFile inode = storedBlock.getINode();
426+
if (inode == null) {
413427
NameNode.stateChangeLog.info("BLOCK NameSystem.markBlockAsCorrupt: " +
414-
"block " + blk + " could not be marked " +
415-
"as corrupt as it does not exists in " +
416-
"blocksMap");
428+
"block " + storedBlock +
429+
" could not be marked as corrupt as it" +
430+
" does not belong to any file");
431+
addToInvalidates(storedBlock, node);
432+
return;
433+
}
434+
// Add this replica to corruptReplicas Map
435+
corruptReplicas.addToCorruptReplicasMap(storedBlock, node);
436+
if (countNodes(storedBlock).liveReplicas() > inode.getReplication()) {
437+
// the block is over-replicated so invalidate the replicas immediately
438+
invalidateBlock(storedBlock, node);
417439
} else {
418-
INodeFile inode = storedBlockInfo.getINode();
419-
if (inode == null) {
420-
NameNode.stateChangeLog.info("BLOCK NameSystem.markBlockAsCorrupt: " +
421-
"block " + blk + " could not be marked " +
422-
"as corrupt as it does not belong to " +
423-
"any file");
424-
addToInvalidates(storedBlockInfo, node);
425-
return;
426-
}
427-
// Add this replica to corruptReplicas Map
428-
corruptReplicas.addToCorruptReplicasMap(storedBlockInfo, node);
429-
if (countNodes(storedBlockInfo).liveReplicas() > inode.getReplication()) {
430-
// the block is over-replicated so invalidate the replicas immediately
431-
invalidateBlock(storedBlockInfo, node);
432-
} else {
433-
// add the block to neededReplication
434-
updateNeededReplications(storedBlockInfo, -1, 0);
435-
}
440+
// add the block to neededReplication
441+
updateNeededReplications(storedBlock, -1, 0);
436442
}
437443
}
438444

@@ -843,8 +849,9 @@ public void processReport(DatanodeDescriptor node,
843849
* needed replications if this takes care of the problem.
844850
* @return the block that is stored in blockMap.
845851
*/
846-
private Block addStoredBlock(Block block, DatanodeDescriptor node,
847-
DatanodeDescriptor delNodeHint) {
852+
private Block addStoredBlock(final Block block,
853+
DatanodeDescriptor node,
854+
DatanodeDescriptor delNodeHint) {
848855
BlockInfo storedBlock = blocksMap.getStoredBlock(block);
849856
if (storedBlock == null || storedBlock.getINode() == null) {
850857
// If this block does not belong to anyfile, then we are done.
@@ -857,30 +864,32 @@ private Block addStoredBlock(Block block, DatanodeDescriptor node,
857864
// it will happen in next block report otherwise.
858865
return block;
859866
}
867+
assert storedBlock != null : "Block must be stored by now";
868+
INodeFile fileINode = storedBlock.getINode();
869+
assert fileINode != null : "Block must belong to a file";
860870

861871
// add block to the data-node
862872
boolean added = node.addBlock(storedBlock);
863873

864-
assert storedBlock != null : "Block must be stored by now";
865-
866874
if (block != storedBlock) {
867-
if (block.getNumBytes() >= 0) {
868-
long cursize = storedBlock.getNumBytes();
875+
long cursize = storedBlock.getNumBytes();
876+
long newsize = block.getNumBytes();
877+
if (newsize >= 0) {
869878
if (cursize == 0) {
870-
storedBlock.setNumBytes(block.getNumBytes());
871-
} else if (cursize != block.getNumBytes()) {
879+
storedBlock.setNumBytes(newsize);
880+
} else if (cursize != newsize) {
872881
FSNamesystem.LOG.warn("Inconsistent size for block " + block +
873882
" reported from " + node.getName() +
874883
" current size is " + cursize +
875-
" reported size is " + block.getNumBytes());
884+
" reported size is " + newsize);
876885
try {
877-
if (cursize > block.getNumBytes()) {
886+
if (cursize > newsize) {
878887
// new replica is smaller in size than existing block.
879888
// Mark the new replica as corrupt.
880889
FSNamesystem.LOG.warn("Mark new replica "
881890
+ block + " from " + node.getName() + " as corrupt "
882891
+ "because length is shorter than existing ones");
883-
markBlockAsCorrupt(block, node);
892+
markBlockAsCorrupt(storedBlock, node);
884893
} else {
885894
// new replica is larger in size than existing block.
886895
// Mark pre-existing replicas as corrupt.
@@ -898,50 +907,38 @@ private Block addStoredBlock(Block block, DatanodeDescriptor node,
898907
FSNamesystem.LOG.warn("Mark existing replica "
899908
+ block + " from " + node.getName() + " as corrupt "
900909
+ "because its length is shorter than the new one");
901-
markBlockAsCorrupt(block, nodes[j]);
910+
markBlockAsCorrupt(storedBlock, nodes[j]);
902911
}
903912
//
904913
// change the size of block in blocksMap
905914
//
906-
storedBlock = blocksMap.getStoredBlock(block); // extra look up!
907-
if (storedBlock == null) {
908-
FSNamesystem.LOG.warn("Block " + block + " reported from "
909-
+ node.getName()
910-
+ " does not exist in blockMap. Surprise! Surprise!");
911-
} else {
912-
storedBlock.setNumBytes(block.getNumBytes());
913-
}
915+
storedBlock.setNumBytes(newsize);
914916
}
915917
} catch (IOException e) {
916918
FSNamesystem.LOG.warn("Error in deleting bad block " + block + e);
917919
}
918920
}
919921

920922
// Updated space consumed if required.
921-
INodeFile file = (storedBlock != null) ? storedBlock.getINode() : null;
922-
long diff = (file == null) ? 0 :
923-
(file.getPreferredBlockSize() - storedBlock.getNumBytes());
923+
long diff = fileINode.getPreferredBlockSize() - storedBlock.getNumBytes();
924924

925-
if (diff > 0 && file.isUnderConstruction() &&
925+
if (diff > 0 && fileINode.isUnderConstruction() &&
926926
cursize < storedBlock.getNumBytes()) {
927927
try {
928928
String path = /* For finding parents */
929-
namesystem.leaseManager.findPath((INodeFileUnderConstruction) file);
929+
namesystem.leaseManager.findPath((INodeFileUnderConstruction)fileINode);
930930
namesystem.dir.updateSpaceConsumed(path, 0, -diff
931-
* file.getReplication());
931+
* fileINode.getReplication());
932932
} catch (IOException e) {
933933
FSNamesystem.LOG
934934
.warn("Unexpected exception while updating disk space : "
935935
+ e.getMessage());
936936
}
937937
}
938938
}
939-
block = storedBlock;
940939
}
941-
assert storedBlock == block : "Block must be stored by now";
942940

943941
int curReplicaDelta = 0;
944-
945942
if (added) {
946943
curReplicaDelta = 1;
947944
//
@@ -951,20 +948,20 @@ private Block addStoredBlock(Block block, DatanodeDescriptor node,
951948
//
952949
if (!namesystem.isInSafeMode()) {
953950
NameNode.stateChangeLog.info("BLOCK* NameSystem.addStoredBlock: "
954-
+ "blockMap updated: " + node.getName() + " is added to " + block
955-
+ " size " + block.getNumBytes());
951+
+ "blockMap updated: " + node.getName() + " is added to " +
952+
storedBlock + " size " + storedBlock.getNumBytes());
956953
}
957954
} else {
958955
NameNode.stateChangeLog.warn("BLOCK* NameSystem.addStoredBlock: "
959-
+ "Redundant addStoredBlock request received for " + block + " on "
960-
+ node.getName() + " size " + block.getNumBytes());
956+
+ "Redundant addStoredBlock request received for " + storedBlock
957+
+ " on " + node.getName() + " size " + storedBlock.getNumBytes());
961958
}
962959

963960
// filter out containingNodes that are marked for decommission.
964961
NumberReplicas num = countNodes(storedBlock);
965962
int numLiveReplicas = num.liveReplicas();
966963
int numCurrentReplica = numLiveReplicas
967-
+ pendingReplications.getNumReplicas(block);
964+
+ pendingReplications.getNumReplicas(storedBlock);
968965

969966
// check whether safe replication is reached for the block
970967
namesystem.incrementSafeBlockCount(numCurrentReplica);
@@ -973,39 +970,37 @@ private Block addStoredBlock(Block block, DatanodeDescriptor node,
973970
// if file is being actively written to, then do not check
974971
// replication-factor here. It will be checked when the file is closed.
975972
//
976-
INodeFile fileINode = null;
977-
fileINode = storedBlock.getINode();
978973
if (fileINode.isUnderConstruction()) {
979-
return block;
974+
return storedBlock;
980975
}
981976

982977
// do not handle mis-replicated blocks during startup
983978
if (namesystem.isInSafeMode())
984-
return block;
979+
return storedBlock;
985980

986981
// handle underReplication/overReplication
987982
short fileReplication = fileINode.getReplication();
988983
if (numCurrentReplica >= fileReplication) {
989-
neededReplications.remove(block, numCurrentReplica,
984+
neededReplications.remove(storedBlock, numCurrentReplica,
990985
num.decommissionedReplicas, fileReplication);
991986
} else {
992-
updateNeededReplications(block, curReplicaDelta, 0);
987+
updateNeededReplications(storedBlock, curReplicaDelta, 0);
993988
}
994989
if (numCurrentReplica > fileReplication) {
995-
processOverReplicatedBlock(block, fileReplication, node, delNodeHint);
990+
processOverReplicatedBlock(storedBlock, fileReplication, node, delNodeHint);
996991
}
997992
// If the file replication has reached desired value
998993
// we can remove any corrupt replicas the block may have
999-
int corruptReplicasCount = corruptReplicas.numCorruptReplicas(block);
994+
int corruptReplicasCount = corruptReplicas.numCorruptReplicas(storedBlock);
1000995
int numCorruptNodes = num.corruptReplicas();
1001996
if (numCorruptNodes != corruptReplicasCount) {
1002997
FSNamesystem.LOG.warn("Inconsistent number of corrupt replicas for " +
1003-
block + "blockMap has " + numCorruptNodes +
998+
storedBlock + "blockMap has " + numCorruptNodes +
1004999
" but corrupt replicas map has " + corruptReplicasCount);
10051000
}
10061001
if ((corruptReplicasCount > 0) && (numLiveReplicas >= fileReplication))
1007-
invalidateCorruptReplicas(block);
1008-
return block;
1002+
invalidateCorruptReplicas(storedBlock);
1003+
return storedBlock;
10091004
}
10101005

10111006
/**

src/java/org/apache/hadoop/hdfs/server/namenode/FSDirectory.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,7 @@ Block addBlock(String path, INode[] inodes, Block block
276276
fileNode.getPreferredBlockSize()*fileNode.getReplication());
277277

278278
// associate the new list of blocks with this file
279-
getBlockManager().addINode(block, fileNode);
280-
BlockInfo blockInfo = getBlockManager().getStoredBlock(block);
279+
BlockInfo blockInfo = getBlockManager().addINode(block, fileNode);
281280
fileNode.addBlock(blockInfo);
282281

283282
NameNode.stateChangeLog.debug("DIR* FSDirectory.addFile: "

src/java/org/apache/hadoop/hdfs/server/namenode/FSNamesystem.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ ExportedAccessKeys getAccessKeys() {
581581
* return the length of the added block; 0 if the block is not added
582582
*/
583583
private long addBlock(Block block, List<BlockWithLocations> results) {
584-
ArrayList<String> machineSet = blockManager.addBlock(block);
584+
ArrayList<String> machineSet = blockManager.getValidLocations(block);
585585
if(machineSet.size() == 0) {
586586
return 0;
587587
} else {
@@ -1337,7 +1337,7 @@ synchronized boolean checkFileProgress(INodeFile v, boolean checkall) {
13371337
*/
13381338
public synchronized void markBlockAsCorrupt(Block blk, DatanodeInfo dn)
13391339
throws IOException {
1340-
blockManager.markBlockAsCorrupt(blk, dn);
1340+
blockManager.findAndMarkBlockAsCorrupt(blk, dn);
13411341
}
13421342

13431343

0 commit comments

Comments
 (0)