1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.client;
20
21 import static org.mockito.Matchers.anyObject;
22 import static org.mockito.Mockito.doReturn;
23 import static org.mockito.Mockito.mock;
24 import static org.mockito.Mockito.reset;
25 import static org.mockito.Mockito.times;
26 import static org.mockito.Mockito.verify;
27
28 import java.math.BigDecimal;
29 import java.util.List;
30 import java.util.NavigableMap;
31 import java.util.Random;
32
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.hadoop.hbase.HBaseTestingUtility;
36 import org.apache.hadoop.hbase.HConstants;
37 import org.apache.hadoop.hbase.HRegionInfo;
38 import org.apache.hadoop.hbase.MetaTableAccessor;
39 import org.apache.hadoop.hbase.ServerName;
40 import org.apache.hadoop.hbase.TableName;
41 import org.apache.hadoop.hbase.TableNotFoundException;
42 import org.apache.hadoop.hbase.testclassification.MediumTests;
43 import org.apache.hadoop.hbase.util.Bytes;
44 import org.apache.hadoop.hbase.util.StoppableImplementation;
45 import org.apache.hadoop.hbase.util.Threads;
46 import org.apache.hadoop.util.StringUtils;
47 import org.junit.After;
48 import org.junit.Assert;
49 import org.junit.Test;
50 import org.junit.experimental.categories.Category;
51
52 @Category(MediumTests.class)
53 public class TestMetaScanner {
54 final Log LOG = LogFactory.getLog(getClass());
55 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
56 private Connection connection;
57
58 @SuppressWarnings("JUnit4SetUpNotRun")
59 public void setUp() throws Exception {
60 TEST_UTIL.startMiniCluster(1);
61 this.connection = TEST_UTIL.getConnection();
62 }
63
64 @After
65 public void tearDown() throws Exception {
66 TEST_UTIL.shutdownMiniCluster();
67 }
68
69 @Test
70 public void testMetaScanner() throws Exception {
71 LOG.info("Starting testMetaScanner");
72
73 setUp();
74 final TableName TABLENAME = TableName.valueOf("testMetaScanner");
75 final byte[] FAMILY = Bytes.toBytes("family");
76 final byte[][] SPLIT_KEYS =
77 new byte[][] { Bytes.toBytes("region_a"), Bytes.toBytes("region_b") };
78
79 TEST_UTIL.createTable(TABLENAME, FAMILY, SPLIT_KEYS);
80 HTable table = (HTable) connection.getTable(TABLENAME);
81
82 TEST_UTIL.countRows(table);
83
84 MetaScanner.MetaScannerVisitor visitor =
85 mock(MetaScanner.MetaScannerVisitor.class);
86 doReturn(true).when(visitor).processRow((Result)anyObject());
87
88
89 MetaScanner.metaScan(connection, visitor, TABLENAME);
90 verify(visitor, times(3)).processRow((Result)anyObject());
91
92
93
94 reset(visitor);
95 doReturn(true).when(visitor).processRow((Result)anyObject());
96 MetaScanner.metaScan(connection, visitor, TABLENAME, HConstants.EMPTY_BYTE_ARRAY, 1000);
97 verify(visitor, times(3)).processRow((Result)anyObject());
98
99
100
101 reset(visitor);
102 doReturn(true).when(visitor).processRow((Result)anyObject());
103 MetaScanner.metaScan(connection, visitor, TABLENAME, Bytes.toBytes("region_ac"), 1000);
104 verify(visitor, times(2)).processRow((Result)anyObject());
105
106
107 reset(visitor);
108 doReturn(true).when(visitor).processRow((Result) anyObject());
109 MetaScanner.metaScan(connection, visitor, TABLENAME, Bytes.toBytes("region_ac"), 1);
110 verify(visitor, times(1)).processRow((Result) anyObject());
111
112
113 try {
114 MetaScanner.metaScan(connection, visitor, TABLENAME, Bytes.toBytes("region_ac"), 1,
115 TableName.valueOf("invalidMeta"));
116 Assert.fail("Passed invalid meta table name but it is not honored");
117 } catch (TableNotFoundException e) {
118 }
119
120 table.close();
121 }
122
123 @Test
124 public void testConcurrentMetaScannerAndCatalogJanitor() throws Throwable {
125
126
127
128
129 TEST_UTIL.getConfiguration().setLong("hbase.catalogjanitor.interval", 500);
130 setUp();
131
132 final long runtime = 30 * 1000;
133 LOG.info("Starting testConcurrentMetaScannerAndCatalogJanitor");
134 final TableName TABLENAME =
135 TableName.valueOf("testConcurrentMetaScannerAndCatalogJanitor");
136 final byte[] FAMILY = Bytes.toBytes("family");
137 TEST_UTIL.createTable(TABLENAME, FAMILY);
138
139 class RegionMetaSplitter extends StoppableImplementation implements Runnable {
140 Random random = new Random();
141 Throwable ex = null;
142 @Override
143 public void run() {
144 while (!isStopped()) {
145 try {
146 List<HRegionInfo> regions = MetaScanner.listAllRegions(TEST_UTIL.getConfiguration(),
147 connection, false);
148
149
150 HRegionInfo parent = regions.get(random.nextInt(regions.size()));
151 if (parent == null || !TABLENAME.equals(parent.getTable())) {
152 continue;
153 }
154
155 long startKey = 0, endKey = Long.MAX_VALUE;
156 byte[] start = parent.getStartKey();
157 byte[] end = parent.getEndKey();
158 if (!Bytes.equals(HConstants.EMPTY_START_ROW, parent.getStartKey())) {
159 startKey = Bytes.toLong(parent.getStartKey());
160 }
161 if (!Bytes.equals(HConstants.EMPTY_END_ROW, parent.getEndKey())) {
162 endKey = Bytes.toLong(parent.getEndKey());
163 }
164 if (startKey == endKey) {
165 continue;
166 }
167
168 long midKey = BigDecimal.valueOf(startKey).add(BigDecimal.valueOf(endKey))
169 .divideToIntegralValue(BigDecimal.valueOf(2)).longValue();
170
171 HRegionInfo splita = new HRegionInfo(TABLENAME,
172 start,
173 Bytes.toBytes(midKey));
174 HRegionInfo splitb = new HRegionInfo(TABLENAME,
175 Bytes.toBytes(midKey),
176 end);
177
178 MetaTableAccessor.splitRegion(connection,
179 parent, splita, splitb, ServerName.valueOf("fooserver", 1, 0), 1);
180
181 Threads.sleep(random.nextInt(200));
182 } catch (Throwable e) {
183 ex = e;
184 Assert.fail(StringUtils.stringifyException(e));
185 }
186 }
187 }
188 void rethrowExceptionIfAny() throws Throwable {
189 if (ex != null) { throw ex; }
190 }
191 }
192
193 class MetaScannerVerifier extends StoppableImplementation implements Runnable {
194 Random random = new Random();
195 Throwable ex = null;
196 @Override
197 public void run() {
198 while(!isStopped()) {
199 try {
200 NavigableMap<HRegionInfo, ServerName> regions =
201 MetaScanner.allTableRegions(connection, TABLENAME);
202
203 LOG.info("-------");
204 byte[] lastEndKey = HConstants.EMPTY_START_ROW;
205 for (HRegionInfo hri: regions.navigableKeySet()) {
206 long startKey = 0, endKey = Long.MAX_VALUE;
207 if (!Bytes.equals(HConstants.EMPTY_START_ROW, hri.getStartKey())) {
208 startKey = Bytes.toLong(hri.getStartKey());
209 }
210 if (!Bytes.equals(HConstants.EMPTY_END_ROW, hri.getEndKey())) {
211 endKey = Bytes.toLong(hri.getEndKey());
212 }
213 LOG.info("start:" + startKey + " end:" + endKey + " hri:" + hri);
214 Assert.assertTrue("lastEndKey=" + Bytes.toString(lastEndKey) + ", startKey=" +
215 Bytes.toString(hri.getStartKey()), Bytes.equals(lastEndKey, hri.getStartKey()));
216 lastEndKey = hri.getEndKey();
217 }
218 Assert.assertTrue(Bytes.equals(lastEndKey, HConstants.EMPTY_END_ROW));
219 LOG.info("-------");
220 Threads.sleep(10 + random.nextInt(50));
221 } catch (Throwable e) {
222 ex = e;
223 Assert.fail(StringUtils.stringifyException(e));
224 }
225 }
226 }
227 void rethrowExceptionIfAny() throws Throwable {
228 if (ex != null) { throw ex; }
229 }
230 }
231
232 RegionMetaSplitter regionMetaSplitter = new RegionMetaSplitter();
233 MetaScannerVerifier metaScannerVerifier = new MetaScannerVerifier();
234
235 Thread regionMetaSplitterThread = new Thread(regionMetaSplitter);
236 Thread metaScannerVerifierThread = new Thread(metaScannerVerifier);
237
238 regionMetaSplitterThread.start();
239 metaScannerVerifierThread.start();
240
241 Threads.sleep(runtime);
242
243 regionMetaSplitter.stop("test finished");
244 metaScannerVerifier.stop("test finished");
245
246 regionMetaSplitterThread.join();
247 metaScannerVerifierThread.join();
248
249 regionMetaSplitter.rethrowExceptionIfAny();
250 metaScannerVerifier.rethrowExceptionIfAny();
251 }
252
253 }