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.HRegionLocation;
24  import org.apache.hadoop.hbase.RegionLoad;
25  import org.apache.hadoop.hbase.ServerLoad;
26  import org.apache.hadoop.hbase.ServerName;
27  import org.apache.hadoop.hbase.testclassification.SmallTests;
28  import org.apache.hadoop.hbase.client.Admin;
29  import org.apache.hadoop.hbase.TableName;
30  import org.apache.hadoop.hbase.client.RegionLocator;
31  import org.junit.Test;
32  import org.junit.experimental.categories.Category;
33  import org.mockito.Mockito;
34  
35  import java.io.IOException;
36  import java.util.ArrayList;
37  import java.util.List;
38  import java.util.Map;
39  import java.util.TreeMap;
40  
41  import static org.junit.Assert.assertEquals;
42  import static org.mockito.Mockito.mock;
43  import static org.mockito.Mockito.when;
44  
45  @Category(SmallTests.class)
46  public class TestRegionSizeCalculator {
47  
48    private Configuration configuration = new Configuration();
49    private final long megabyte = 1024L * 1024L;
50  
51    @Test
52    public void testSimpleTestCase() throws Exception {
53  
54      RegionLocator regionLocator = mockRegionLocator("region1", "region2", "region3");
55  
56      Admin admin = mockAdmin(
57        mockServer(
58          mockRegion("region1", 123),
59          mockRegion("region3", 1232)
60        ),
61        mockServer(
62          mockRegion("region2",  54321),
63          mockRegion("otherTableRegion", 110)
64        )
65      );
66  
67      RegionSizeCalculator calculator = new RegionSizeCalculator(regionLocator, admin);
68  
69      assertEquals(123 * megabyte, calculator.getRegionSize("region1".getBytes()));
70      assertEquals(54321 * megabyte, calculator.getRegionSize("region2".getBytes()));
71      assertEquals(1232 * megabyte, calculator.getRegionSize("region3".getBytes()));
72      // if region is not inside our table, it should return 0
73      assertEquals(0 * megabyte, calculator.getRegionSize("otherTableRegion".getBytes()));
74  
75      assertEquals(3, calculator.getRegionSizeMap().size());
76    }
77  
78  
79    /**
80     * When size of region in megabytes is larger than largest possible integer there could be
81     * error caused by lost of precision.
82     * */
83    @Test
84    public void testLargeRegion() throws Exception {
85  
86      RegionLocator regionLocator = mockRegionLocator("largeRegion");
87  
88      Admin admin = mockAdmin(
89        mockServer(
90          mockRegion("largeRegion", Integer.MAX_VALUE)
91        )
92      );
93  
94      RegionSizeCalculator calculator = new RegionSizeCalculator(regionLocator, admin);
95  
96      assertEquals(((long) Integer.MAX_VALUE) * megabyte, calculator.getRegionSize("largeRegion".getBytes()));
97    }
98  
99    /** When calculator is disabled, it should return 0 for each request.*/
100   @Test
101   public void testDisabled() throws Exception {
102     String regionName = "cz.goout:/index.html";
103     RegionLocator table = mockRegionLocator(regionName);
104 
105     Admin admin = mockAdmin(
106       mockServer(
107         mockRegion(regionName, 999)
108       )
109     );
110 
111     //first request on enabled calculator
112     RegionSizeCalculator calculator = new RegionSizeCalculator(table, admin);
113     assertEquals(999 * megabyte, calculator.getRegionSize(regionName.getBytes()));
114 
115     //then disabled calculator.
116     configuration.setBoolean(RegionSizeCalculator.ENABLE_REGIONSIZECALCULATOR, false);
117     RegionSizeCalculator disabledCalculator = new RegionSizeCalculator(table, admin);
118     assertEquals(0 * megabyte, disabledCalculator.getRegionSize(regionName.getBytes()));
119 
120     assertEquals(0, disabledCalculator.getRegionSizeMap().size());
121   }
122 
123   /**
124    * Makes some table with given region names.
125    * */
126   private RegionLocator mockRegionLocator(String... regionNames) throws IOException {
127     RegionLocator mockedTable = Mockito.mock(RegionLocator.class);
128     when(mockedTable.getName()).thenReturn(TableName.valueOf("sizeTestTable"));
129     List<HRegionLocation> regionLocations = new ArrayList<>();
130     when(mockedTable.getAllRegionLocations()).thenReturn(regionLocations);
131 
132     for (String regionName : regionNames) {
133       HRegionInfo info = Mockito.mock(HRegionInfo.class);
134       when(info.getRegionName()).thenReturn(regionName.getBytes());
135       regionLocations.add(new HRegionLocation(info, null));//we are not interested in values
136     }
137 
138     return mockedTable;
139   }
140 
141   /**
142    * Creates mock returning ClusterStatus info about given servers.
143   */
144   private Admin mockAdmin(ServerLoad... servers) throws Exception {
145     //get clusterstatus
146     Admin mockAdmin = Mockito.mock(Admin.class);
147     ClusterStatus clusterStatus = mockCluster(servers);
148     when(mockAdmin.getConfiguration()).thenReturn(configuration);
149     when(mockAdmin.getClusterStatus()).thenReturn(clusterStatus);
150     return mockAdmin;
151   }
152 
153   /**
154    * Creates mock of region with given name and size.
155    *
156    * @param  fileSizeMb number of megabytes occupied by region in file store in megabytes
157    * */
158   private RegionLoad mockRegion(String regionName, int fileSizeMb) {
159     RegionLoad region = Mockito.mock(RegionLoad.class);
160     when(region.getName()).thenReturn(regionName.getBytes());
161     when(region.getNameAsString()).thenReturn(regionName);
162     when(region.getStorefileSizeMB()).thenReturn(fileSizeMb);
163     return region;
164   }
165 
166   private ClusterStatus mockCluster(ServerLoad[] servers) {
167     List<ServerName> serverNames = new ArrayList<ServerName>();
168 
169     ClusterStatus clusterStatus = Mockito.mock(ClusterStatus.class);
170     when(clusterStatus.getServers()).thenReturn(serverNames);
171 
172     int serverCounter = 0;
173     for (ServerLoad server : servers) {
174       ServerName serverName = mock(ServerName.class);
175       when(serverName.getServerName()).thenReturn("server" + (serverCounter++));
176       serverNames.add(serverName);
177       when(clusterStatus.getLoad(serverName)).thenReturn(server);
178     }
179 
180     return clusterStatus;
181   }
182 
183   /** Creates mock of region server with given regions*/
184   private ServerLoad mockServer(RegionLoad... regions) {
185     ServerLoad serverLoad = Mockito.mock(ServerLoad.class);
186     Map<byte[], RegionLoad> regionMap = new TreeMap<byte[], RegionLoad>(Bytes.BYTES_COMPARATOR);
187 
188     for (RegionLoad regionName : regions) {
189       regionMap.put(regionName.getName(), regionName);
190     }
191 
192     when(serverLoad.getRegionsLoad()).thenReturn(regionMap);
193     return serverLoad;
194   }
195 
196 }