/* * * Licensed 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.hdfs.server.datanode; import io.hops.leader_election.node.ActiveNode; import io.hops.leader_election.node.ActiveNodePBImpl; import io.hops.leader_election.node.SortedActiveNodeList; import io.hops.leader_election.node.SortedActiveNodeListPBImpl; import io.hops.metadata.HdfsStorageFactory; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.hdfs.*; import org.apache.hadoop.hdfs.server.blockmanagement.BRTrackingService; import org.apache.hadoop.hdfs.server.namenode.NameNode; import org.apache.hadoop.hdfs.server.protocol.DatanodeProtocol; import org.apache.hadoop.hdfs.server.protocol.DatanodeRegistration; import org.apache.hadoop.hdfs.server.protocol.StorageBlockReport; import org.apache.hadoop.test.GenericTestUtils; import org.apache.hadoop.util.ExitUtil; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import static org.junit.Assert.*; /** * * @author salman */ public class TestBlockReportLoadBalancing1 { public static final Log LOG = LogFactory.getLog(TestBlockReportLoadBalancing1.class); private MiniDFSCluster cluster; @Before public void startUpCluster() throws IOException { } @After public void shutDownCluster() throws Exception { if (cluster != null) { cluster.shutdown(); cluster = null; Thread.sleep(1000); } } @Test public void TestBRTrackingService_01() throws IOException, InterruptedException { final int NN_COUNT = 5; final long DFS_BR_LB_TIME_WINDOW_SIZE = 5000; final long DFS_BR_LB_MAX_BLK_PER_NN_PER_TW = 100000; final long DFS_BR_LB_DB_VAR_UPDATE_THRESHOLD = 1000; Configuration conf = new Configuration(); conf.setLong(DFSConfigKeys.DFS_BR_LB_MAX_BLK_PER_TW, NN_COUNT*DFS_BR_LB_MAX_BLK_PER_NN_PER_TW); HdfsStorageFactory.setConfiguration(conf); assert (HdfsStorageFactory.formatStorage()); List<ActiveNode> list = new ArrayList<ActiveNode>(); for (int i = 0; i < NN_COUNT; i++) { ActiveNodePBImpl anode = new ActiveNodePBImpl(i, "host", "localhost", i, "0.0.0.0:10000"); list.add(anode); } SortedActiveNodeListPBImpl nnList = new SortedActiveNodeListPBImpl(list); BRTrackingService service = new BRTrackingService( DFS_BR_LB_DB_VAR_UPDATE_THRESHOLD, DFS_BR_LB_TIME_WINDOW_SIZE); for (int i = 0; i < NN_COUNT; i++) { ActiveNode an = assignWork(nnList, service,(long) (DFS_BR_LB_MAX_BLK_PER_NN_PER_TW * 0.8)); assertTrue("Unable to assign work", an != null); } for (int i = 0; i < NN_COUNT; i++) { ActiveNode an = assignWork(nnList, service, (long) (DFS_BR_LB_MAX_BLK_PER_NN_PER_TW * 0.2)); assertTrue("Unable to assign work", an != null); } // more work assignment should fail ActiveNode an = assignWork(nnList, service, 10000); assertTrue("More work should not have been assigned", an==null); an = assignWork(nnList, service, 1); assertTrue("More work should not have been assigned", an==null); // sleep. All history will be cleared after that and more work can be assigned Thread.sleep(DFS_BR_LB_TIME_WINDOW_SIZE); for (int i = 0; i < NN_COUNT; i++) { an = assignWork(nnList, service, DFS_BR_LB_MAX_BLK_PER_NN_PER_TW); assertTrue("Unable to assign work", an != null); } // more work assignment should fail an = assignWork(nnList, service, 10000); assertTrue("More work should not have been assigned", an==null); an = assignWork(nnList, service, 1); assertTrue("More work should not have been assigned", an==null); } @Test //add and remove namenodes public void TestBRTrackingService_02() throws IOException, InterruptedException { final int NN_COUNT = 5; final long DFS_BR_LB_TIME_WINDOW_SIZE = 5000; final long DFS_BR_LB_MAX_BLK_PER_NN_PER_TW = 100000; final long DFS_BR_LB_DB_VAR_UPDATE_THRESHOLD = 1000; Configuration conf = new Configuration(); conf.setLong(DFSConfigKeys.DFS_BR_LB_MAX_BLK_PER_TW, NN_COUNT*DFS_BR_LB_MAX_BLK_PER_NN_PER_TW); HdfsStorageFactory.setConfiguration(conf); assert (HdfsStorageFactory.formatStorage()); List<ActiveNode> list = new ArrayList<ActiveNode>(); for (int i = 0; i < NN_COUNT; i++) { ActiveNodePBImpl anode = new ActiveNodePBImpl(i, "host", "localhost", i, "0.0.0.0:10000"); list.add(anode); } SortedActiveNodeListPBImpl nnList = new SortedActiveNodeListPBImpl(list); BRTrackingService service = new BRTrackingService(DFS_BR_LB_DB_VAR_UPDATE_THRESHOLD, DFS_BR_LB_TIME_WINDOW_SIZE); for (int i = 0; i < NN_COUNT; i++) { ActiveNode an = assignWork(nnList, service, (long) (DFS_BR_LB_MAX_BLK_PER_NN_PER_TW * 1)); assertTrue("Unable to assign work", an != null); } // more work assignment should fail ActiveNode an = assignWork(nnList, service, 10000); assertTrue("More work should not have been assigned", an==null); an = assignWork(nnList, service, 1); assertTrue("More work should not have been assigned", an==null); // sleep. All history will be cleared after that and more work can be assigned Thread.sleep(DFS_BR_LB_TIME_WINDOW_SIZE); // kill a NN list.remove(0); nnList = new SortedActiveNodeListPBImpl(list); for (int i = 0; i < NN_COUNT; i++) { an = assignWork(nnList, service, (long) (DFS_BR_LB_MAX_BLK_PER_NN_PER_TW * 1)); assertTrue("Unable to assign work", an != null); } // more work assignment should fail an = assignWork(nnList, service, 1); assertTrue("More work should not have been assigned", an==null); Thread.sleep(DFS_BR_LB_TIME_WINDOW_SIZE); // add more namenodes for (int i = NN_COUNT; i < 2 * NN_COUNT; i++) { ActiveNodePBImpl anode = new ActiveNodePBImpl(i, "host", "localhost", i, "0.0.0.0:10000"); list.add(anode); } nnList = new SortedActiveNodeListPBImpl(list); for (int i = 0; i < NN_COUNT; i++) { an = assignWork(nnList, service, (long) (DFS_BR_LB_MAX_BLK_PER_NN_PER_TW * 0.25)); assertTrue("Unable to assign work", an != null); } for (int i = 0; i < NN_COUNT; i++) { an = assignWork(nnList, service, (long) (DFS_BR_LB_MAX_BLK_PER_NN_PER_TW * 0.75)); assertTrue("Unable to assign work", an != null); } // more work assignment should fail an = assignWork(nnList, service, 1); assertTrue("More work should not have been assigned", an==null); } @Test public void TestCommandLine() throws IOException, InterruptedException { MiniDFSCluster cluster = null; final int NN_COUNT = 5; final long DFS_BR_LB_TIME_WINDOW_SIZE = 5000; final long DFS_BR_LB_MAX_BLK_PER_NN_PER_TW = 100000; final long DFS_BR_LB_DB_VAR_UPDATE_THRESHOLD = 1000; Configuration conf = new Configuration(); conf.setLong(DFSConfigKeys.DFS_BR_LB_MAX_BLK_PER_TW, NN_COUNT*DFS_BR_LB_MAX_BLK_PER_NN_PER_TW); HdfsStorageFactory.setConfiguration(conf); assert (HdfsStorageFactory.formatStorage()); List<ActiveNode> list = new ArrayList<ActiveNode>(); for (int i = 0; i < NN_COUNT; i++) { ActiveNodePBImpl anode = new ActiveNodePBImpl(i, "host", "localhost", i, "0.0.0.0:10000"); list.add(anode); } SortedActiveNodeListPBImpl nnList = new SortedActiveNodeListPBImpl(list); BRTrackingService service = new BRTrackingService( DFS_BR_LB_DB_VAR_UPDATE_THRESHOLD, DFS_BR_LB_TIME_WINDOW_SIZE); for (int i = 0; i < NN_COUNT; i++) { ActiveNode an = assignWork(nnList,service, (long) (DFS_BR_LB_MAX_BLK_PER_NN_PER_TW * 1)); assertTrue("Unable to assign work", an != null); } // more work assignment should fail ActiveNode an = assignWork(nnList,service, 10000); assertTrue("More work should not have been assigned", an == null); an = assignWork(nnList,service, 1); assertTrue("More work should not have been assigned", an == null); String[] argv = {"-setBlkRptProcessSize", NN_COUNT*DFS_BR_LB_MAX_BLK_PER_NN_PER_TW * 2 + ""}; try { NameNode.createNameNode(argv, conf); } catch (ExitUtil.ExitException e) { assertEquals("setBlkRptProcessSize command should succeed", 0, e.status); } // sleep. All history will be cleared after that and more work can be assigned Thread.sleep(DFS_BR_LB_TIME_WINDOW_SIZE); for (int i = 0; i < NN_COUNT; i++) { an = assignWork(nnList,service, (long) (DFS_BR_LB_MAX_BLK_PER_NN_PER_TW * 2)); assertTrue("Unable to assign work", an != null); } } @Test public void TestClusterWithOutDataNodes() throws IOException, InterruptedException { final int NN_COUNT = 5; final long DFS_BR_LB_TIME_WINDOW_SIZE = 5000; final long DFS_BR_LB_MAX_BLK_PER_NN_PER_TW = 100000; final long DFS_BR_LB_DB_VAR_UPDATE_THRESHOLD = 1000; Configuration conf = new Configuration(); conf.setLong(DFSConfigKeys.DFS_BR_LB_MAX_BLK_PER_TW, NN_COUNT * DFS_BR_LB_MAX_BLK_PER_NN_PER_TW); conf.setLong(DFSConfigKeys.DFS_BR_LB_TIME_WINDOW_SIZE, DFS_BR_LB_TIME_WINDOW_SIZE); conf.setLong(DFSConfigKeys.DFS_BR_LB_DB_VAR_UPDATE_THRESHOLD,DFS_BR_LB_DB_VAR_UPDATE_THRESHOLD); cluster = new MiniDFSCluster.Builder(conf) .nnTopology(MiniDFSNNTopology.simpleHOPSTopology(NN_COUNT)) .format(true).numDataNodes(0).build(); cluster.waitActive(); ActiveNode an = null; for (int i = 0; i < NN_COUNT; i++) { an = cluster.getNameNode(0).getNextNamenodeToSendBlockReport(DFS_BR_LB_MAX_BLK_PER_NN_PER_TW); assertTrue("Unable to assign work", an != null); } // more work assignment should fail try { an = cluster.getNameNode(0).getNextNamenodeToSendBlockReport(DFS_BR_LB_MAX_BLK_PER_NN_PER_TW); fail("More work should not have been assigned"); }catch(BRLoadBalancingException e){ } String[] argv = {"-setBlkRptProcessSize", NN_COUNT * DFS_BR_LB_MAX_BLK_PER_NN_PER_TW * 2 + ""}; try { NameNode.createNameNode(argv, conf); } catch (ExitUtil.ExitException e) { assertEquals("setBlkRptProcessSize command should succeed", 0, e.status); } // sleep. All history will be cleared after that and more work can be assigned Thread.sleep(DFS_BR_LB_TIME_WINDOW_SIZE); for (int i = 0; i < NN_COUNT; i++) { an = cluster.getNameNode(0).getNextNamenodeToSendBlockReport(DFS_BR_LB_MAX_BLK_PER_NN_PER_TW*2); assertTrue("Unable to assign work", an != null); } // now kill some namenodes cluster.shutdownNameNode(NN_COUNT-1); cluster.shutdownNameNode(NN_COUNT-2); // sleep. All history will be cleared after that and more work can be assigned Thread.sleep(DFS_BR_LB_TIME_WINDOW_SIZE); for (int i = 0; i < NN_COUNT; i++) { an = cluster.getNameNode(0).getNextNamenodeToSendBlockReport((long)(DFS_BR_LB_MAX_BLK_PER_NN_PER_TW*0.5)); an = cluster.getNameNode(0).getNextNamenodeToSendBlockReport((long)(DFS_BR_LB_MAX_BLK_PER_NN_PER_TW)); an = cluster.getNameNode(0).getNextNamenodeToSendBlockReport((long)(DFS_BR_LB_MAX_BLK_PER_NN_PER_TW*0.5)); assertTrue("Unable to assign work", an != null); } try { an = cluster.getNameNode(0).getNextNamenodeToSendBlockReport(DFS_BR_LB_MAX_BLK_PER_NN_PER_TW * 2); fail("More work should not have been assigned"); }catch(BRLoadBalancingException e){ } cluster.shutdown(); } private static ActiveNode assignWork(SortedActiveNodeList nnList, BRTrackingService service, long blks){ try { return service.assignWork(nnList,blks); }catch (Exception e){ return null; } } }