[120] | 1 | package org.apache.hadoop.hdfs.server.namenode; |
---|
| 2 | |
---|
| 3 | import java.util.Collection; |
---|
| 4 | import java.util.Iterator; |
---|
| 5 | |
---|
| 6 | import org.apache.hadoop.conf.Configuration; |
---|
| 7 | import org.apache.hadoop.fs.FileSystem; |
---|
| 8 | import org.apache.hadoop.fs.Path; |
---|
| 9 | import org.apache.hadoop.hdfs.DFSTestUtil; |
---|
| 10 | import org.apache.hadoop.hdfs.MiniDFSCluster; |
---|
| 11 | import org.apache.hadoop.hdfs.MiniDFSCluster.DataNodeProperties; |
---|
| 12 | import org.apache.hadoop.hdfs.protocol.Block; |
---|
| 13 | import org.apache.hadoop.hdfs.server.namenode.FSNamesystem.NumberReplicas; |
---|
| 14 | |
---|
| 15 | import junit.framework.TestCase; |
---|
| 16 | |
---|
| 17 | /** |
---|
| 18 | * Test if live nodes count per node is correct |
---|
| 19 | * so NN makes right decision for under/over-replicated blocks |
---|
| 20 | */ |
---|
| 21 | public class TestNodeCount extends TestCase { |
---|
| 22 | public void testNodeCount() throws Exception { |
---|
| 23 | // start a mini dfs cluster of 2 nodes |
---|
| 24 | final Configuration conf = new Configuration(); |
---|
| 25 | final short REPLICATION_FACTOR = (short)2; |
---|
| 26 | final MiniDFSCluster cluster = |
---|
| 27 | new MiniDFSCluster(conf, REPLICATION_FACTOR, true, null); |
---|
| 28 | try { |
---|
| 29 | final FSNamesystem namesystem = cluster.getNameNode().namesystem; |
---|
| 30 | final FileSystem fs = cluster.getFileSystem(); |
---|
| 31 | |
---|
| 32 | // populate the cluster with a one block file |
---|
| 33 | final Path FILE_PATH = new Path("/testfile"); |
---|
| 34 | DFSTestUtil.createFile(fs, FILE_PATH, 1L, REPLICATION_FACTOR, 1L); |
---|
| 35 | DFSTestUtil.waitReplication(fs, FILE_PATH, REPLICATION_FACTOR); |
---|
| 36 | Block block = DFSTestUtil.getFirstBlock(fs, FILE_PATH); |
---|
| 37 | |
---|
| 38 | // keep a copy of all datanode descriptor |
---|
| 39 | DatanodeDescriptor[] datanodes = (DatanodeDescriptor[]) |
---|
| 40 | namesystem.heartbeats.toArray(new DatanodeDescriptor[REPLICATION_FACTOR]); |
---|
| 41 | |
---|
| 42 | // start two new nodes |
---|
| 43 | cluster.startDataNodes(conf, 2, true, null, null); |
---|
| 44 | cluster.waitActive(); |
---|
| 45 | |
---|
| 46 | // bring down first datanode |
---|
| 47 | DatanodeDescriptor datanode = datanodes[0]; |
---|
| 48 | DataNodeProperties dnprop = cluster.stopDataNode(datanode.getName()); |
---|
| 49 | // make sure that NN detects that the datanode is down |
---|
| 50 | synchronized (namesystem.heartbeats) { |
---|
| 51 | datanode.setLastUpdate(0); // mark it dead |
---|
| 52 | namesystem.heartbeatCheck(); |
---|
| 53 | } |
---|
| 54 | // the block will be replicated |
---|
| 55 | DFSTestUtil.waitReplication(fs, FILE_PATH, REPLICATION_FACTOR); |
---|
| 56 | |
---|
| 57 | // restart the first datanode |
---|
| 58 | cluster.restartDataNode(dnprop); |
---|
| 59 | cluster.waitActive(); |
---|
| 60 | |
---|
| 61 | // check if excessive replica is detected |
---|
| 62 | NumberReplicas num = null; |
---|
| 63 | do { |
---|
| 64 | synchronized (namesystem) { |
---|
| 65 | num = namesystem.countNodes(block); |
---|
| 66 | } |
---|
| 67 | } while (num.excessReplicas() == 0); |
---|
| 68 | |
---|
| 69 | // find out a non-excess node |
---|
| 70 | Iterator<DatanodeDescriptor> iter = namesystem.blocksMap.nodeIterator(block); |
---|
| 71 | DatanodeDescriptor nonExcessDN = null; |
---|
| 72 | while (iter.hasNext()) { |
---|
| 73 | DatanodeDescriptor dn = iter.next(); |
---|
| 74 | Collection<Block> blocks = namesystem.excessReplicateMap.get(dn.getStorageID()); |
---|
| 75 | if (blocks == null || !blocks.contains(block) ) { |
---|
| 76 | nonExcessDN = dn; |
---|
| 77 | break; |
---|
| 78 | } |
---|
| 79 | } |
---|
| 80 | assertTrue(nonExcessDN!=null); |
---|
| 81 | |
---|
| 82 | // bring down non excessive datanode |
---|
| 83 | dnprop = cluster.stopDataNode(nonExcessDN.getName()); |
---|
| 84 | // make sure that NN detects that the datanode is down |
---|
| 85 | synchronized (namesystem.heartbeats) { |
---|
| 86 | nonExcessDN.setLastUpdate(0); // mark it dead |
---|
| 87 | namesystem.heartbeatCheck(); |
---|
| 88 | } |
---|
| 89 | |
---|
| 90 | // The block should be replicated |
---|
| 91 | do { |
---|
| 92 | num = namesystem.countNodes(block); |
---|
| 93 | } while (num.liveReplicas() != REPLICATION_FACTOR); |
---|
| 94 | |
---|
| 95 | // restart the first datanode |
---|
| 96 | cluster.restartDataNode(dnprop); |
---|
| 97 | cluster.waitActive(); |
---|
| 98 | |
---|
| 99 | // check if excessive replica is detected |
---|
| 100 | do { |
---|
| 101 | num = namesystem.countNodes(block); |
---|
| 102 | } while (num.excessReplicas() == 2); |
---|
| 103 | } finally { |
---|
| 104 | cluster.shutdown(); |
---|
| 105 | } |
---|
| 106 | } |
---|
| 107 | } |
---|