| /* |
| * 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.hdfs.server.blockmanagement; |
| |
| import java.util.Arrays; |
| import java.util.Iterator; |
| import java.util.Random; |
| |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.hadoop.hdfs.protocol.DatanodeID; |
| import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeDescriptor; |
| import org.apache.hadoop.hdfs.server.blockmanagement.DatanodeDescriptor.CachedBlocksList; |
| import org.apache.hadoop.hdfs.server.namenode.CachedBlock; |
| import org.junit.Assert; |
| import org.junit.Test; |
| |
| public class TestCachedBlocksList { |
| public static final Log LOG = LogFactory.getLog(TestCachedBlocksList.class); |
| |
| @Test(timeout=60000) |
| public void testSingleList() { |
| DatanodeDescriptor dn = new DatanodeDescriptor( |
| new DatanodeID("127.0.0.1", "localhost", "abcd", 5000, 5001, 5002, 5003)); |
| CachedBlock[] blocks = new CachedBlock[] { |
| new CachedBlock(0L, (short)1, true), |
| new CachedBlock(1L, (short)1, true), |
| new CachedBlock(2L, (short)1, true), |
| }; |
| // check that lists are empty |
| Assert.assertTrue("expected pending cached list to start off empty.", |
| !dn.getPendingCached().iterator().hasNext()); |
| Assert.assertTrue("expected cached list to start off empty.", |
| !dn.getCached().iterator().hasNext()); |
| Assert.assertTrue("expected pending uncached list to start off empty.", |
| !dn.getPendingUncached().iterator().hasNext()); |
| // add a block to the back |
| Assert.assertTrue(dn.getCached().add(blocks[0])); |
| Assert.assertTrue("expected pending cached list to still be empty.", |
| !dn.getPendingCached().iterator().hasNext()); |
| Assert.assertEquals("failed to insert blocks[0]", blocks[0], |
| dn.getCached().iterator().next()); |
| Assert.assertTrue("expected pending uncached list to still be empty.", |
| !dn.getPendingUncached().iterator().hasNext()); |
| // add another block to the back |
| Assert.assertTrue(dn.getCached().add(blocks[1])); |
| Iterator<CachedBlock> iter = dn.getCached().iterator(); |
| Assert.assertEquals(blocks[0], iter.next()); |
| Assert.assertEquals(blocks[1], iter.next()); |
| Assert.assertTrue(!iter.hasNext()); |
| // add a block to the front |
| Assert.assertTrue(dn.getCached().addFirst(blocks[2])); |
| iter = dn.getCached().iterator(); |
| Assert.assertEquals(blocks[2], iter.next()); |
| Assert.assertEquals(blocks[0], iter.next()); |
| Assert.assertEquals(blocks[1], iter.next()); |
| Assert.assertTrue(!iter.hasNext()); |
| // remove a block from the middle |
| Assert.assertTrue(dn.getCached().remove(blocks[0])); |
| iter = dn.getCached().iterator(); |
| Assert.assertEquals(blocks[2], iter.next()); |
| Assert.assertEquals(blocks[1], iter.next()); |
| Assert.assertTrue(!iter.hasNext()); |
| // remove all blocks |
| dn.getCached().clear(); |
| Assert.assertTrue("expected cached list to be empty after clear.", |
| !dn.getPendingCached().iterator().hasNext()); |
| } |
| |
| private void testAddElementsToList(CachedBlocksList list, |
| CachedBlock[] blocks) { |
| Assert.assertTrue("expected list to start off empty.", |
| !list.iterator().hasNext()); |
| for (CachedBlock block : blocks) { |
| Assert.assertTrue(list.add(block)); |
| } |
| } |
| |
| private void testRemoveElementsFromList(Random r, |
| CachedBlocksList list, CachedBlock[] blocks) { |
| int i = 0; |
| for (Iterator<CachedBlock> iter = list.iterator(); iter.hasNext(); ) { |
| Assert.assertEquals(blocks[i], iter.next()); |
| i++; |
| } |
| if (r.nextBoolean()) { |
| LOG.info("Removing via iterator"); |
| for (Iterator<CachedBlock> iter = list.iterator(); iter.hasNext() ;) { |
| iter.next(); |
| iter.remove(); |
| } |
| } else { |
| LOG.info("Removing in pseudo-random order"); |
| CachedBlock[] remainingBlocks = Arrays.copyOf(blocks, blocks.length); |
| for (int removed = 0; removed < remainingBlocks.length; ) { |
| int toRemove = r.nextInt(remainingBlocks.length); |
| if (remainingBlocks[toRemove] != null) { |
| Assert.assertTrue(list.remove(remainingBlocks[toRemove])); |
| remainingBlocks[toRemove] = null; |
| removed++; |
| } |
| } |
| } |
| Assert.assertTrue("expected list to be empty after everything " + |
| "was removed.", !list.iterator().hasNext()); |
| } |
| |
| @Test(timeout=60000) |
| public void testMultipleLists() { |
| DatanodeDescriptor[] datanodes = new DatanodeDescriptor[] { |
| new DatanodeDescriptor( |
| new DatanodeID("127.0.0.1", "localhost", "abcd", 5000, 5001, 5002, 5003)), |
| new DatanodeDescriptor( |
| new DatanodeID("127.0.1.1", "localhost", "efgh", 6000, 6001, 6002, 6003)), |
| }; |
| CachedBlocksList[] lists = new CachedBlocksList[] { |
| datanodes[0].getPendingCached(), |
| datanodes[0].getCached(), |
| datanodes[1].getPendingCached(), |
| datanodes[1].getCached(), |
| datanodes[1].getPendingUncached(), |
| }; |
| final int NUM_BLOCKS = 8000; |
| CachedBlock[] blocks = new CachedBlock[NUM_BLOCKS]; |
| for (int i = 0; i < NUM_BLOCKS; i++) { |
| blocks[i] = new CachedBlock(i, (short)i, true); |
| } |
| Random r = new Random(654); |
| for (CachedBlocksList list : lists) { |
| testAddElementsToList(list, blocks); |
| } |
| for (CachedBlocksList list : lists) { |
| testRemoveElementsFromList(r, list, blocks); |
| } |
| } |
| } |