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