From a4baabe4a41fb50bd86205cdecf977a17d4324fe Mon Sep 17 00:00:00 2001 From: Hairong Kuang Date: Wed, 2 Nov 2011 16:31:21 +0000 Subject: [PATCH] HDFS-2477. Optimize computing the diff between a block report and the namenode state. Contributed by Tomasz Nykiel. git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1196676 13f79535-47bb-0310-9956-ffa450edef68 --- hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt | 3 + .../server/blockmanagement/BlockInfo.java | 55 ++++++++++++++++++- .../server/blockmanagement/BlockManager.java | 11 +++- .../blockmanagement/DatanodeDescriptor.java | 17 ++++-- 4 files changed, 78 insertions(+), 8 deletions(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt index 2a7f7532954..a1bcbc28225 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt +++ b/hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt @@ -52,6 +52,9 @@ Trunk (unreleased changes) HDFS-2334. Add Closeable to JournalManager. (Ivan Kelly via jitendra) + HDFS-2477. Optimize computing the diff between a block report and the + namenode state. (Tomasz Nykiel via hairong) + BUG FIXES HDFS-2287. TestParallelRead has a small off-by-one bug. (todd) diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockInfo.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockInfo.java index 293d5c59699..c66c5cf3de2 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockInfo.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockInfo.java @@ -122,6 +122,38 @@ void setNext(int index, BlockInfo to) { triplets[index*3+2] = to; } + /** + * Return the previous block on the block list for the datanode at + * position index. Set the previous block on the list to "to". + * + * @param index - the datanode index + * @param to - block to be set to previous on the list of blocks + * @return current previous block on the list of blocks + */ + BlockInfo getSetPrevious(int index, BlockInfo to) { + assert this.triplets != null : "BlockInfo is not initialized"; + assert index >= 0 && index*3+1 < triplets.length : "Index is out of bound"; + BlockInfo info = (BlockInfo)triplets[index*3+1]; + triplets[index*3+1] = to; + return info; + } + + /** + * Return the next block on the block list for the datanode at + * position index. Set the next block on the list to "to". + * + * @param index - the datanode index + * @param to - block to be set to next on the list of blocks + * * @return current next block on the list of blocks + */ + BlockInfo getSetNext(int index, BlockInfo to) { + assert this.triplets != null : "BlockInfo is not initialized"; + assert index >= 0 && index*3+2 < triplets.length : "Index is out of bound"; + BlockInfo info = (BlockInfo)triplets[index*3+2]; + triplets[index*3+2] = to; + return info; + } + int getCapacity() { assert this.triplets != null : "BlockInfo is not initialized"; assert triplets.length % 3 == 0 : "Malformed BlockInfo"; @@ -259,6 +291,27 @@ public BlockInfo listRemove(BlockInfo head, DatanodeDescriptor dn) { return head; } + /** + * Remove this block from the list of blocks related to the specified + * DatanodeDescriptor. Insert it into the head of the list of blocks. + * + * @return the new head of the list. + */ + public BlockInfo moveBlockToHead(BlockInfo head, DatanodeDescriptor dn, + int curIndex, int headIndex) { + if (head == this) { + return this; + } + BlockInfo next = this.getSetNext(curIndex, head); + BlockInfo prev = this.getSetPrevious(curIndex, null); + + head.setPrevious(headIndex, this); + prev.setNext(prev.findDatanode(dn), next); + if (next != null) + next.setPrevious(next.findDatanode(dn), prev); + return this; + } + /** * BlockInfo represents a block that is not being constructed. * In order to start modifying the block, the BlockInfo should be converted @@ -317,4 +370,4 @@ public LightWeightGSet.LinkedElement getNext() { public void setNext(LightWeightGSet.LinkedElement next) { this.nextLinkedElement = next; } -} \ No newline at end of file +} diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockManager.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockManager.java index 250781320c7..04afa4a1dc3 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockManager.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/BlockManager.java @@ -75,6 +75,7 @@ */ @InterfaceAudience.Private public class BlockManager { + static final Log LOG = LogFactory.getLog(BlockManager.class); /** Default load factor of map */ @@ -1443,7 +1444,10 @@ private void reportDiff(DatanodeDescriptor dn, BlockInfo delimiter = new BlockInfo(new Block(), 1); boolean added = dn.addBlock(delimiter); assert added : "Delimiting block cannot be present in the node"; - if(newReport == null) + int headIndex = 0; //currently the delimiter is in the head of the list + int curIndex; + + if (newReport == null) newReport = new BlockListAsLongs(); // scan the report and process newly reported blocks BlockReportIterator itBR = newReport.getBlockReportIterator(); @@ -1453,8 +1457,9 @@ private void reportDiff(DatanodeDescriptor dn, BlockInfo storedBlock = processReportedBlock(dn, iblk, iState, toAdd, toInvalidate, toCorrupt, toUC); // move block to the head of the list - if(storedBlock != null && storedBlock.findDatanode(dn) >= 0) - dn.moveBlockToHead(storedBlock); + if (storedBlock != null && (curIndex = storedBlock.findDatanode(dn)) >= 0) { + headIndex = dn.moveBlockToHead(storedBlock, curIndex, headIndex); + } } // collect blocks that have not been reported // all of them are next to the delimiter diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/DatanodeDescriptor.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/DatanodeDescriptor.java index 0f310d36ebd..2ad49b7fa55 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/DatanodeDescriptor.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/DatanodeDescriptor.java @@ -244,15 +244,24 @@ public boolean removeBlock(BlockInfo b) { /** * Move block to the head of the list of blocks belonging to the data-node. + * @return the index of the head of the blockList */ - void moveBlockToHead(BlockInfo b) { - blockList = b.listRemove(blockList, this); - blockList = b.listInsert(blockList, this); + int moveBlockToHead(BlockInfo b, int curIndex, int headIndex) { + blockList = b.moveBlockToHead(blockList, this, curIndex, headIndex); + return curIndex; + } + + /** + * Used for testing only + * @return the head of the blockList + */ + protected BlockInfo getHead(){ + return blockList; } /** * Replace specified old block with a new one in the DataNodeDescriptor. - * + * * @param oldBlock - block to be replaced * @param newBlock - a replacement block * @return the new block