View Javadoc

1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.util;
19  
20  import org.apache.hadoop.conf.Configuration;
21  import org.apache.hadoop.hbase.ClusterStatus;
22  import org.apache.hadoop.hbase.HRegionInfo;
23  import org.apache.hadoop.hbase.RegionLoad;
24  import org.apache.hadoop.hbase.ServerLoad;
25  import org.apache.hadoop.hbase.ServerName;
26  import org.apache.hadoop.hbase.SmallTests;
27  import org.apache.hadoop.hbase.client.HBaseAdmin;
28  import org.apache.hadoop.hbase.client.HTable;
29  import org.junit.Test;
30  import org.junit.experimental.categories.Category;
31  import org.mockito.Mockito;
32  
33  import java.io.IOException;
34  import java.util.ArrayList;
35  import java.util.List;
36  import java.util.Map;
37  import java.util.NavigableMap;
38  import java.util.TreeMap;
39  
40  import static org.junit.Assert.assertEquals;
41  import static org.mockito.Mockito.mock;
42  import static org.mockito.Mockito.when;
43  
44  @Category(SmallTests.class)
45  public class TestRegionSizeCalculator {
46  
47    private Configuration configuration = new Configuration();
48    private final long megabyte = 1024L * 1024L;
49  
50    @Test
51    public void testSimpleTestCase() throws Exception {
52  
53      HTable table = mockTable("region1", "region2", "region3");
54  
55      HBaseAdmin admin = mockAdmin(
56        mockServer(
57          mockRegion("region1", 123),
58          mockRegion("region3", 1232)
59        ),
60        mockServer(
61          mockRegion("region2",  54321),
62          mockRegion("otherTableRegion", 110)
63        )
64      );
65  
66      RegionSizeCalculator calculator = new RegionSizeCalculator(table, admin);
67  
68      assertEquals(123 * megabyte, calculator.getRegionSize("region1".getBytes()));
69      assertEquals(54321 * megabyte, calculator.getRegionSize("region2".getBytes()));
70      assertEquals(1232 * megabyte, calculator.getRegionSize("region3".getBytes()));
71      // if region is not inside our table, it should return 0
72      assertEquals(0 * megabyte, calculator.getRegionSize("otherTableRegion".getBytes()));
73  
74      assertEquals(3, calculator.getRegionSizeMap().size());
75    }
76  
77  
78    /**
79     * When size of region in megabytes is larger than largest possible integer there could be
80     * error caused by lost of precision.
81     * */
82    @Test
83    public void testLargeRegion() throws Exception {
84  
85      HTable table = mockTable("largeRegion");
86  
87      HBaseAdmin admin = mockAdmin(
88        mockServer(
89          mockRegion("largeRegion", Integer.MAX_VALUE)
90        )
91      );
92  
93      RegionSizeCalculator calculator = new RegionSizeCalculator(table, admin);
94  
95      assertEquals(((long) Integer.MAX_VALUE) * megabyte, calculator.getRegionSize("largeRegion".getBytes()));
96    }
97  
98    /** When calculator is disabled, it should return 0 for each request.*/
99    @Test
100   public void testDisabled() throws Exception {
101     String regionName = "cz.goout:/index.html";
102     HTable table = mockTable(regionName);
103 
104     HBaseAdmin admin = mockAdmin(
105       mockServer(
106         mockRegion(regionName, 999)
107       )
108     );
109 
110     //first request on enabled calculator
111     RegionSizeCalculator calculator = new RegionSizeCalculator(table, admin);
112     assertEquals(999 * megabyte, calculator.getRegionSize(regionName.getBytes()));
113 
114     //then disabled calculator.
115     configuration.setBoolean(RegionSizeCalculator.ENABLE_REGIONSIZECALCULATOR, false);
116     RegionSizeCalculator disabledCalculator = new RegionSizeCalculator(table, admin);
117     assertEquals(0 * megabyte, disabledCalculator.getRegionSize(regionName.getBytes()));
118 
119     assertEquals(0, disabledCalculator.getRegionSizeMap().size());
120   }
121 
122   /**
123    * Makes some table with given region names.
124    * */
125   private HTable mockTable(String... regionNames) throws IOException {
126     HTable mockedTable = Mockito.mock(HTable.class);
127     when(mockedTable.getConfiguration()).thenReturn(configuration);
128     when(mockedTable.getTableName()).thenReturn("sizeTestTable".getBytes());
129     NavigableMap<HRegionInfo, ServerName> regionLocations = new TreeMap<HRegionInfo, ServerName>();
130     when(mockedTable.getRegionLocations()).thenReturn(regionLocations);
131 
132     for (String regionName : regionNames) {
133       HRegionInfo info = Mockito.mock(HRegionInfo.class);
134       when(info.getRegionName()).thenReturn(regionName.getBytes());
135       regionLocations.put(info, null);//we are not interested in values
136     }
137 
138     return mockedTable;
139   }
140 
141   /**
142    * Creates mock returing ClusterStatus info about given servers.
143   */
144   private HBaseAdmin mockAdmin(ServerLoad... servers) throws Exception {
145     //get clusterstatus
146     HBaseAdmin mockAdmin = Mockito.mock(HBaseAdmin.class);
147     ClusterStatus clusterStatus = mockCluster(servers);
148     when(mockAdmin.getClusterStatus()).thenReturn(clusterStatus);
149     return mockAdmin;
150   }
151 
152   /**
153    * Creates mock of region with given name and size.
154    *
155    * @param  fileSizeMb number of megabytes occupied by region in file store in megabytes
156    * */
157   private RegionLoad mockRegion(String regionName, int fileSizeMb) {
158     RegionLoad region = Mockito.mock(RegionLoad.class);
159     when(region.getName()).thenReturn(regionName.getBytes());
160     when(region.getNameAsString()).thenReturn(regionName);
161     when(region.getStorefileSizeMB()).thenReturn(fileSizeMb);
162     return region;
163   }
164 
165   private ClusterStatus mockCluster(ServerLoad[] servers) {
166     List<ServerName> serverNames = new ArrayList<ServerName>();
167 
168     ClusterStatus clusterStatus = Mockito.mock(ClusterStatus.class);
169     when(clusterStatus.getServers()).thenReturn(serverNames);
170 
171     int serverCounter = 0;
172     for (ServerLoad server : servers) {
173       ServerName serverName = mock(ServerName.class);
174       when(serverName.getServerName()).thenReturn("server" + (serverCounter++));
175       serverNames.add(serverName);
176       when(clusterStatus.getLoad(serverName)).thenReturn(server);
177     }
178 
179     return clusterStatus;
180   }
181 
182   /** Creates mock of region server with given regions*/
183   private ServerLoad mockServer(RegionLoad... regions) {
184     ServerLoad serverLoad = Mockito.mock(ServerLoad.class);
185     Map<byte[], RegionLoad> regionMap = new TreeMap<byte[], RegionLoad>(Bytes.BYTES_COMPARATOR);
186 
187     for (RegionLoad regionName : regions) {
188       regionMap.put(regionName.getName(), regionName);
189     }
190 
191     when(serverLoad.getRegionsLoad()).thenReturn(regionMap);
192     return serverLoad;
193   }
194 
195 }