Author: rangadi
Date: Mon Jul 14 11:06:52 2008
New Revision: 676668
URL: http://svn.apache.org/viewvc?rev=676668&view=rev
Log:
HADOOP-3707. NameNode keeps a count of number of blocks scheduled
to be written to a datanode and uses it to avoid allocating more
blocks than a datanode can hold. (rangadi)
Added:
hadoop/core/branches/branch-0.17/src/test/org/apache/hadoop/dfs/TestBlocksScheduledCounter.java
Modified:
hadoop/core/branches/branch-0.17/CHANGES.txt
hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/DatanodeDescriptor.java
hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/FSNamesystem.java
hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/ReplicationTargetChooser.java
hadoop/core/branches/branch-0.17/src/webapps/dfs/dfshealth.jsp
Modified: hadoop/core/branches/branch-0.17/CHANGES.txt
URL:
http://svn.apache.org/viewvc/hadoop/core/branches/branch-0.17/CHANGES.txt?rev=676668&r1=676667&r2=676668&view=diff
==============================================================================
--- hadoop/core/branches/branch-0.17/CHANGES.txt (original)
+++ hadoop/core/branches/branch-0.17/CHANGES.txt Mon Jul 14 11:06:52 2008
@@ -4,6 +4,10 @@
BUG FIXES
+ HADOOP-3707. NameNode keeps a count of number of blocks scheduled
+ to be written to a datanode and uses it to avoid allocating more
+ blocks than a datanode can hold. (rangadi)
+
HADOOP-3681. DFSClient can get into an infinite loop while closing
a file if there are some errors. (Lohit Vijayarenu via rangadi)
Modified:
hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/DatanodeDescriptor.java
URL:
http://svn.apache.org/viewvc/hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/DatanodeDescriptor.java?rev=676668&r1=676667&r2=676668&view=diff
==============================================================================
---
hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/DatanodeDescriptor.java
(original)
+++
hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/DatanodeDescriptor.java
Mon Jul 14 11:06:52 2008
@@ -49,6 +49,16 @@
Set<Block> invalidateBlocks;
boolean processedBlockReport = false;
+ /* Variables for maintaning number of blocks scheduled to be written to
+ * this datanode. This count is approximate and might be slightly higger
+ * in case of errors (e.g. datanode does not report if an error occurs
+ * while writing the block).
+ */
+ private int currApproxBlocksScheduled = 0;
+ private int prevApproxBlocksScheduled = 0;
+ private long lastBlocksScheduledRollTime = 0;
+ private static final int BLOCKS_SCHEDULED_ROLL_INTERVAL = 300 * 1000; // 5
min
+
/** Default constructor */
public DatanodeDescriptor() {
super();
@@ -181,6 +191,7 @@
this.remaining = remaining;
this.lastUpdate = System.currentTimeMillis();
this.xceiverCount = xceiverCount;
+ rollBlocksScheduled(lastUpdate);
}
/**
@@ -367,4 +378,43 @@
toRemove.add(it.next());
this.removeBlock(delimiter);
}
+
+ /**
+ * @return Approximate number of blocks currently scheduled to be written
+ * to this datanode.
+ */
+ int getBlocksScheduled() {
+ return currApproxBlocksScheduled + prevApproxBlocksScheduled;
+ }
+
+ /**
+ * Increments counter for number of blocks scheduled.
+ */
+ void incBlocksScheduled() {
+ currApproxBlocksScheduled++;
+ }
+
+ /**
+ * Decrements counter for number of blocks scheduled.
+ */
+ void decBlocksScheduled() {
+ if (prevApproxBlocksScheduled > 0) {
+ prevApproxBlocksScheduled--;
+ } else if (currApproxBlocksScheduled > 0) {
+ currApproxBlocksScheduled--;
+ }
+ // its ok if both counters are zero.
+ }
+
+ /**
+ * Adjusts curr and prev number of blocks scheduled every few minutes.
+ */
+ private void rollBlocksScheduled(long now) {
+ if ((now - lastBlocksScheduledRollTime) >
+ BLOCKS_SCHEDULED_ROLL_INTERVAL) {
+ prevApproxBlocksScheduled = currApproxBlocksScheduled;
+ currApproxBlocksScheduled = 0;
+ lastBlocksScheduledRollTime = now;
+ }
+ }
}
Modified:
hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/FSNamesystem.java
URL:
http://svn.apache.org/viewvc/hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/FSNamesystem.java?rev=676668&r1=676667&r2=676668&view=diff
==============================================================================
---
hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/FSNamesystem.java
(original)
+++
hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/FSNamesystem.java
Mon Jul 14 11:06:52 2008
@@ -1147,6 +1147,10 @@
minReplication);
}
+ for (DatanodeDescriptor dn : targets) {
+ dn.incBlocksScheduled();
+ }
+
// Allocate a new block and record it in the INode.
synchronized (this) {
INodeFileUnderConstruction pendingFile = checkLease(src, clientName);
@@ -2402,6 +2406,10 @@
srcNode.addBlockToBeReplicated(block, targets);
scheduledReplicationCount++;
+ for (DatanodeDescriptor dn : targets) {
+ dn.incBlocksScheduled();
+ }
+
// Move the block-replication into a "pending" state.
// The reason we use 'pending' is so we can retry
// replications that fail after an appropriate amount of time.
@@ -3093,6 +3101,9 @@
throw new DisallowedDatanodeException(node);
}
+ // decrement number of blocks scheduled to this datanode.
+ node.decBlocksScheduled();
+
// get the deletion hint node
DatanodeDescriptor delHintNode = null;
if(delHint!=null && delHint.length()!=0) {
Modified:
hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/ReplicationTargetChooser.java
URL:
http://svn.apache.org/viewvc/hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/ReplicationTargetChooser.java?rev=676668&r1=676667&r2=676668&view=diff
==============================================================================
---
hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/ReplicationTargetChooser.java
(original)
+++
hadoop/core/branches/branch-0.17/src/java/org/apache/hadoop/dfs/ReplicationTargetChooser.java
Mon Jul 14 11:06:52 2008
@@ -398,8 +398,10 @@
return false;
}
+ long remaining = node.getRemaining() -
+ (node.getBlocksScheduled() * blockSize);
// check the remaining capacity of the target machine
- if (blockSize* FSConstants.MIN_BLOCKS_FOR_WRITE>node.getRemaining()) {
+ if (blockSize* FSConstants.MIN_BLOCKS_FOR_WRITE>remaining) {
logr.debug("Node "+NodeBase.getPath(node)+
" is not chosen because the node does not have enough space");
return false;
Added:
hadoop/core/branches/branch-0.17/src/test/org/apache/hadoop/dfs/TestBlocksScheduledCounter.java
URL:
http://svn.apache.org/viewvc/hadoop/core/branches/branch-0.17/src/test/org/apache/hadoop/dfs/TestBlocksScheduledCounter.java?rev=676668&view=auto
==============================================================================
---
hadoop/core/branches/branch-0.17/src/test/org/apache/hadoop/dfs/TestBlocksScheduledCounter.java
(added)
+++
hadoop/core/branches/branch-0.17/src/test/org/apache/hadoop/dfs/TestBlocksScheduledCounter.java
Mon Jul 14 11:06:52 2008
@@ -0,0 +1,63 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.dfs;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.dfs.DFSClient.DFSOutputStream;
+import org.apache.hadoop.fs.FSDataOutputStream;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+
+import junit.framework.TestCase;
+
+/**
+ * This class tests DatanodeDescriptor.getBlocksScheduled() at the
+ * NameNode. This counter is supposed to keep track of blocks currently
+ * scheduled to a datanode.
+ */
+public class TestBlocksScheduledCounter extends TestCase {
+
+ public void testBlocksScheduledCounter() throws IOException {
+
+ MiniDFSCluster cluster = new MiniDFSCluster(new Configuration(), 1,
+ true, null);
+ cluster.waitActive();
+ FileSystem fs = cluster.getFileSystem();
+
+ //open a file an write a few bytes:
+ FSDataOutputStream out = fs.create(new Path("/testBlockScheduledCounter"));
+ for (int i=0; i<1024; i++) {
+ out.write(i);
+ }
+ // flush to make sure a block is allocated.
+ ((DFSOutputStream)(out.getWrappedStream())).fsync();
+
+ ArrayList<DatanodeDescriptor> dnList = new ArrayList<DatanodeDescriptor>();
+ cluster.getNameNode().namesystem.DFSNodesStatus(dnList, dnList);
+ DatanodeDescriptor dn = dnList.get(0);
+
+ assertEquals(1, dn.getBlocksScheduled());
+
+ // close the file and the counter should go to zero.
+ out.close();
+ assertEquals(0, dn.getBlocksScheduled());
+ }
+}
Modified: hadoop/core/branches/branch-0.17/src/webapps/dfs/dfshealth.jsp
URL:
http://svn.apache.org/viewvc/hadoop/core/branches/branch-0.17/src/webapps/dfs/dfshealth.jsp?rev=676668&r1=676667&r2=676668&view=diff
==============================================================================
--- hadoop/core/branches/branch-0.17/src/webapps/dfs/dfshealth.jsp (original)
+++ hadoop/core/branches/branch-0.17/src/webapps/dfs/dfshealth.jsp Mon Jul 14
11:06:52 2008
@@ -106,7 +106,8 @@
JspHelper.percentageGraph( (int)Double.parseDouble(percentUsed) ,
100) +
"<td class=\"size\">" +
FsShell.limitDecimalTo2(d.getRemaining()*1.0/diskBytes) +
- "<td class=\"blocks\">" + d.numBlocks() + "\n");
+ "<td title=" + "\"blocks scheduled : " + d.getBlocksScheduled()
+
+ "\" class=\"blocks\">" + d.numBlocks() + "\n");
}
public void generateDFSHealthReport(JspWriter out,