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.regionserver;
19  
20  import static org.junit.Assert.*;
21  
22  import java.io.IOException;
23  import java.util.TreeMap;
24  
25  import org.apache.hadoop.conf.Configuration;
26  import org.apache.hadoop.hbase.HBaseConfiguration;
27  import org.apache.hadoop.hbase.HRegionInfo;
28  import org.apache.hadoop.hbase.HTableDescriptor;
29  import org.apache.hadoop.hbase.util.Bytes;
30  import org.junit.Before;
31  import org.junit.Test;
32  import org.mockito.Mockito;
33  
34  public class TestRegionSplitPolicy {
35  
36    private Configuration conf;
37    private HTableDescriptor htd;
38    private HRegion mockRegion;
39    private TreeMap<byte[], Store> stores;
40  
41    @Before
42    public void setupMocks() {
43      conf = HBaseConfiguration.create();
44  
45      HRegionInfo hri = new HRegionInfo(Bytes.toBytes("testtable"));
46  
47      htd = new HTableDescriptor();
48      mockRegion = Mockito.mock(HRegion.class);
49      Mockito.doReturn(htd).when(mockRegion).getTableDesc();
50      Mockito.doReturn(hri).when(mockRegion).getRegionInfo();
51      
52      stores = new TreeMap<byte[], Store>(Bytes.BYTES_COMPARATOR);
53      Mockito.doReturn(stores).when(mockRegion).getStores();
54    }
55    
56    @Test
57    public void testCreateDefault() throws IOException {
58      conf.setLong("hbase.hregion.max.filesize", 1234L);
59      
60      // Using a default HTD, should pick up the file size from
61      // configuration.
62      ConstantSizeRegionSplitPolicy policy =
63          (ConstantSizeRegionSplitPolicy)RegionSplitPolicy.create(
64              mockRegion, conf);
65      assertEquals(1234L, policy.getDesiredMaxFileSize());
66      
67      // If specified in HTD, should use that
68      htd.setMaxFileSize(9999L);
69      policy = (ConstantSizeRegionSplitPolicy)RegionSplitPolicy.create(
70          mockRegion, conf);
71      assertEquals(9999L, policy.getDesiredMaxFileSize());    
72    }
73    
74    @Test
75    public void testConstantSizePolicy() throws IOException {
76      htd.setMaxFileSize(1024L);
77      
78      ConstantSizeRegionSplitPolicy policy =
79        (ConstantSizeRegionSplitPolicy)RegionSplitPolicy.create(mockRegion, conf);
80      
81      // For no stores, should not split
82      assertFalse(policy.shouldSplit());
83  
84      // Add a store above the requisite size. Should split.
85      Store mockStore = Mockito.mock(Store.class);
86      Mockito.doReturn(2000L).when(mockStore).getSize();
87      Mockito.doReturn(true).when(mockStore).canSplit();
88      stores.put(new byte[]{1}, mockStore);
89      
90      assertTrue(policy.shouldSplit());
91      
92      // Act as if there's a reference file or some other reason it can't split.
93      // This should prevent splitting even though it's big enough.
94      Mockito.doReturn(false).when(mockStore).canSplit();
95      assertFalse(policy.shouldSplit());
96  
97      // Reset splittability after above
98      Mockito.doReturn(true).when(mockStore).canSplit();
99      
100     // Set to a small size but turn on forceSplit. Should result in a split.
101     Mockito.doReturn(true).when(mockRegion).shouldForceSplit();
102     Mockito.doReturn(100L).when(mockStore).getSize();
103     assertTrue(policy.shouldSplit());
104     
105     // Turn off forceSplit, should not split
106     Mockito.doReturn(false).when(mockRegion).shouldForceSplit();
107     assertFalse(policy.shouldSplit());
108   }
109   
110   @Test
111   public void testGetSplitPoint() throws IOException {
112     ConstantSizeRegionSplitPolicy policy =
113       (ConstantSizeRegionSplitPolicy)RegionSplitPolicy.create(mockRegion, conf);
114     
115     // For no stores, should not split
116     assertFalse(policy.shouldSplit());
117     assertNull(policy.getSplitPoint());
118     
119     // Add a store above the requisite size. Should split.
120     Store mockStore = Mockito.mock(Store.class);
121     Mockito.doReturn(2000L).when(mockStore).getSize();
122     Mockito.doReturn(true).when(mockStore).canSplit();
123     Mockito.doReturn(Bytes.toBytes("store 1 split"))
124       .when(mockStore).getSplitPoint();
125     stores.put(new byte[]{1}, mockStore);
126 
127     assertEquals("store 1 split",
128         Bytes.toString(policy.getSplitPoint()));
129     
130     // Add a bigger store. The split point should come from that one
131     Store mockStore2 = Mockito.mock(Store.class);
132     Mockito.doReturn(4000L).when(mockStore2).getSize();
133     Mockito.doReturn(true).when(mockStore2).canSplit();
134     Mockito.doReturn(Bytes.toBytes("store 2 split"))
135       .when(mockStore2).getSplitPoint();
136     stores.put(new byte[]{2}, mockStore2);
137     
138     assertEquals("store 2 split",
139         Bytes.toString(policy.getSplitPoint()));
140   }
141 }