1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.hadoop.hbase.replication.regionserver;
20
21 import static org.junit.Assert.*;
22 import static org.mockito.Mockito.mock;
23 import static org.mockito.Mockito.when;
24
25 import java.io.IOException;
26 import java.util.List;
27 import java.util.concurrent.Executors;
28 import java.util.concurrent.atomic.AtomicLong;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.commons.logging.impl.Log4JLogger;
33 import org.apache.hadoop.conf.Configuration;
34 import org.apache.hadoop.hbase.HBaseTestingUtility;
35 import org.apache.hadoop.hbase.HConstants;
36 import org.apache.hadoop.hbase.HRegionLocation;
37 import org.apache.hadoop.hbase.HTableDescriptor;
38 import org.apache.hadoop.hbase.testclassification.MediumTests;
39 import org.apache.hadoop.hbase.TableName;
40 import org.apache.hadoop.hbase.Waiter;
41 import org.apache.hadoop.hbase.client.ClusterConnection;
42 import org.apache.hadoop.hbase.client.RpcRetryingCaller;
43 import org.apache.hadoop.hbase.client.Connection;
44 import org.apache.hadoop.hbase.client.ConnectionFactory;
45 import org.apache.hadoop.hbase.client.RegionLocator;
46 import org.apache.hadoop.hbase.client.Table;
47 import org.apache.hadoop.hbase.client.replication.ReplicationAdmin;
48 import org.apache.hadoop.hbase.regionserver.HRegionServer;
49 import org.apache.hadoop.hbase.regionserver.Region;
50 import org.apache.hadoop.hbase.wal.WAL.Entry;
51 import org.apache.hadoop.hbase.wal.WALKey;
52 import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
53 import org.apache.hadoop.hbase.replication.ReplicationException;
54 import org.apache.hadoop.hbase.replication.ReplicationPeerConfig;
55 import org.apache.hadoop.hbase.util.ServerRegionReplicaUtil;
56 import org.apache.hadoop.hbase.zookeeper.ZKUtil;
57 import org.apache.log4j.Level;
58 import org.junit.AfterClass;
59 import org.junit.BeforeClass;
60 import org.junit.Test;
61 import org.junit.experimental.categories.Category;
62
63 import com.google.common.collect.Lists;
64
65
66
67
68
69 @Category(MediumTests.class)
70 public class TestRegionReplicaReplicationEndpoint {
71
72 private static final Log LOG = LogFactory.getLog(TestRegionReplicaReplicationEndpoint.class);
73
74 static {
75 ((Log4JLogger)RpcRetryingCaller.LOG).getLogger().setLevel(Level.ALL);
76 }
77
78 private static final int NB_SERVERS = 2;
79
80 private static final HBaseTestingUtility HTU = new HBaseTestingUtility();
81
82 @BeforeClass
83 public static void beforeClass() throws Exception {
84 Configuration conf = HTU.getConfiguration();
85 conf.setFloat("hbase.regionserver.logroll.multiplier", 0.0003f);
86 conf.setInt("replication.source.size.capacity", 10240);
87 conf.setLong("replication.source.sleepforretries", 100);
88 conf.setInt("hbase.regionserver.maxlogs", 10);
89 conf.setLong("hbase.master.logcleaner.ttl", 10);
90 conf.setInt("zookeeper.recovery.retry", 1);
91 conf.setInt("zookeeper.recovery.retry.intervalmill", 10);
92 conf.setBoolean(HConstants.REPLICATION_ENABLE_KEY, true);
93 conf.setBoolean(ServerRegionReplicaUtil.REGION_REPLICA_REPLICATION_CONF_KEY, true);
94 conf.setLong(HConstants.THREAD_WAKE_FREQUENCY, 100);
95 conf.setInt("replication.stats.thread.period.seconds", 5);
96 conf.setBoolean("hbase.tests.use.shortcircuit.reads", false);
97 conf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 5);
98 conf.setInt("hbase.client.serverside.retries.multiplier", 1);
99
100 HTU.startMiniCluster(NB_SERVERS);
101 }
102
103 @AfterClass
104 public static void afterClass() throws Exception {
105 HTU.shutdownMiniCluster();
106 }
107
108 @Test
109 public void testRegionReplicaReplicationPeerIsCreated() throws IOException, ReplicationException {
110
111
112 ReplicationAdmin admin = new ReplicationAdmin(HTU.getConfiguration());
113 String peerId = "region_replica_replication";
114
115 if (admin.getPeerConfig(peerId) != null) {
116 admin.removePeer(peerId);
117 }
118
119 HTableDescriptor htd = HTU.createTableDescriptor(
120 "testReplicationPeerIsCreated_no_region_replicas");
121 HTU.getHBaseAdmin().createTable(htd);
122 ReplicationPeerConfig peerConfig = admin.getPeerConfig(peerId);
123 assertNull(peerConfig);
124
125 htd = HTU.createTableDescriptor("testReplicationPeerIsCreated");
126 htd.setRegionReplication(2);
127 HTU.getHBaseAdmin().createTable(htd);
128
129
130 peerConfig = admin.getPeerConfig(peerId);
131 assertNotNull(peerConfig);
132 assertEquals(peerConfig.getClusterKey(), ZKUtil.getZooKeeperClusterKey(HTU.getConfiguration()));
133 assertEquals(peerConfig.getReplicationEndpointImpl(),
134 RegionReplicaReplicationEndpoint.class.getName());
135 admin.close();
136 }
137
138 @Test (timeout=240000)
139 public void testRegionReplicaReplicationPeerIsCreatedForModifyTable() throws Exception {
140
141
142 ReplicationAdmin admin = new ReplicationAdmin(HTU.getConfiguration());
143 String peerId = "region_replica_replication";
144
145 if (admin.getPeerConfig(peerId) != null) {
146 admin.removePeer(peerId);
147 }
148
149 HTableDescriptor htd
150 = HTU.createTableDescriptor("testRegionReplicaReplicationPeerIsCreatedForModifyTable");
151 HTU.getHBaseAdmin().createTable(htd);
152
153
154 ReplicationPeerConfig peerConfig = admin.getPeerConfig(peerId);
155 assertNull(peerConfig);
156
157 HTU.getHBaseAdmin().disableTable(htd.getTableName());
158 htd.setRegionReplication(2);
159 HTU.getHBaseAdmin().modifyTable(htd.getTableName(), htd);
160 HTU.getHBaseAdmin().enableTable(htd.getTableName());
161
162
163 peerConfig = admin.getPeerConfig(peerId);
164 assertNotNull(peerConfig);
165 assertEquals(peerConfig.getClusterKey(), ZKUtil.getZooKeeperClusterKey(HTU.getConfiguration()));
166 assertEquals(peerConfig.getReplicationEndpointImpl(),
167 RegionReplicaReplicationEndpoint.class.getName());
168 admin.close();
169 }
170
171 public void testRegionReplicaReplication(int regionReplication) throws Exception {
172
173
174 TableName tableName = TableName.valueOf("testRegionReplicaReplicationWithReplicas_"
175 + regionReplication);
176 HTableDescriptor htd = HTU.createTableDescriptor(tableName.toString());
177 htd.setRegionReplication(regionReplication);
178 HTU.getHBaseAdmin().createTable(htd);
179 TableName tableNameNoReplicas =
180 TableName.valueOf("testRegionReplicaReplicationWithReplicas_NO_REPLICAS");
181 HTU.deleteTableIfAny(tableNameNoReplicas);
182 HTU.createTable(tableNameNoReplicas, HBaseTestingUtility.fam1);
183
184 Connection connection = ConnectionFactory.createConnection(HTU.getConfiguration());
185 Table table = connection.getTable(tableName);
186 Table tableNoReplicas = connection.getTable(tableNameNoReplicas);
187
188 try {
189
190 HTU.loadNumericRows(tableNoReplicas, HBaseTestingUtility.fam1, 6000, 7000);
191
192
193 HTU.loadNumericRows(table, HBaseTestingUtility.fam1, 0, 1000);
194
195 verifyReplication(tableName, regionReplication, 0, 1000);
196
197 } finally {
198 table.close();
199 tableNoReplicas.close();
200 HTU.deleteTableIfAny(tableNameNoReplicas);
201 connection.close();
202 }
203 }
204
205 private void verifyReplication(TableName tableName, int regionReplication,
206 final int startRow, final int endRow) throws Exception {
207 verifyReplication(tableName, regionReplication, startRow, endRow, true);
208 }
209
210 private void verifyReplication(TableName tableName, int regionReplication,
211 final int startRow, final int endRow, final boolean present) throws Exception {
212
213 final Region[] regions = new Region[regionReplication];
214
215 for (int i=0; i < NB_SERVERS; i++) {
216 HRegionServer rs = HTU.getMiniHBaseCluster().getRegionServer(i);
217 List<Region> onlineRegions = rs.getOnlineRegions(tableName);
218 for (Region region : onlineRegions) {
219 regions[region.getRegionInfo().getReplicaId()] = region;
220 }
221 }
222
223 for (Region region : regions) {
224 assertNotNull(region);
225 }
226
227 for (int i = 1; i < regionReplication; i++) {
228 final Region region = regions[i];
229
230 Waiter.waitFor(HTU.getConfiguration(), 90000, new Waiter.Predicate<Exception>() {
231 @Override
232 public boolean evaluate() throws Exception {
233 LOG.info("verifying replication for region replica:" + region.getRegionInfo());
234 try {
235 HTU.verifyNumericRows(region, HBaseTestingUtility.fam1, startRow, endRow, present);
236 } catch(Throwable ex) {
237 LOG.warn("Verification from secondary region is not complete yet", ex);
238
239 return false;
240 }
241 return true;
242 }
243 });
244 }
245 }
246
247 @Test(timeout = 240000)
248 public void testRegionReplicaReplicationWith2Replicas() throws Exception {
249 testRegionReplicaReplication(2);
250 }
251
252 @Test(timeout = 240000)
253 public void testRegionReplicaReplicationWith3Replicas() throws Exception {
254 testRegionReplicaReplication(3);
255 }
256
257 @Test(timeout = 240000)
258 public void testRegionReplicaReplicationWith10Replicas() throws Exception {
259 testRegionReplicaReplication(10);
260 }
261
262 @Test (timeout = 240000)
263 public void testRegionReplicaWithoutMemstoreReplication() throws Exception {
264 int regionReplication = 3;
265 TableName tableName = TableName.valueOf("testRegionReplicaWithoutMemstoreReplication");
266 HTableDescriptor htd = HTU.createTableDescriptor(tableName.toString());
267 htd.setRegionReplication(regionReplication);
268 htd.setRegionMemstoreReplication(false);
269 HTU.getHBaseAdmin().createTable(htd);
270
271 Connection connection = ConnectionFactory.createConnection(HTU.getConfiguration());
272 Table table = connection.getTable(tableName);
273 try {
274
275 final int STEP = 100;
276 for (int i = 0; i < 3; ++i) {
277 final int startRow = i * STEP;
278 final int endRow = (i + 1) * STEP;
279 LOG.info("Writing data from " + startRow + " to " + endRow);
280 HTU.loadNumericRows(table, HBaseTestingUtility.fam1, startRow, endRow);
281 verifyReplication(tableName, regionReplication, startRow, endRow, false);
282
283
284 LOG.info("flushing table");
285 HTU.flush(tableName);
286 verifyReplication(tableName, regionReplication, 0, endRow, true);
287 }
288 } finally {
289 table.close();
290 connection.close();
291 }
292 }
293
294 @Test (timeout = 240000)
295 public void testRegionReplicaReplicationForFlushAndCompaction() throws Exception {
296
297
298
299
300 int regionReplication = 3;
301 TableName tableName = TableName.valueOf("testRegionReplicaReplicationForFlushAndCompaction");
302 HTableDescriptor htd = HTU.createTableDescriptor(tableName.toString());
303 htd.setRegionReplication(regionReplication);
304 HTU.getHBaseAdmin().createTable(htd);
305
306 Connection connection = ConnectionFactory.createConnection(HTU.getConfiguration());
307 Table table = connection.getTable(tableName);
308
309 try {
310
311
312 for (int i = 0; i < 6000; i += 1000) {
313 LOG.info("Writing data from " + i + " to " + (i+1000));
314 HTU.loadNumericRows(table, HBaseTestingUtility.fam1, i, i+1000);
315 LOG.info("flushing table");
316 HTU.flush(tableName);
317 LOG.info("compacting table");
318 HTU.compact(tableName, false);
319 }
320
321 verifyReplication(tableName, regionReplication, 0, 1000);
322 } finally {
323 table.close();
324 connection.close();
325 }
326 }
327
328 @Test (timeout = 240000)
329 public void testRegionReplicaReplicationIgnoresDisabledTables() throws Exception {
330 testRegionReplicaReplicationIgnoresDisabledTables(false);
331 }
332
333 @Test (timeout = 240000)
334 public void testRegionReplicaReplicationIgnoresDroppedTables() throws Exception {
335 testRegionReplicaReplicationIgnoresDisabledTables(true);
336 }
337
338 public void testRegionReplicaReplicationIgnoresDisabledTables(boolean dropTable)
339 throws Exception {
340
341
342
343 TableName tableName = TableName.valueOf("testRegionReplicaReplicationIgnoresDisabledTables"
344 + dropTable);
345 HTableDescriptor htd = HTU.createTableDescriptor(tableName.toString());
346 int regionReplication = 3;
347 htd.setRegionReplication(regionReplication);
348 HTU.deleteTableIfAny(tableName);
349 HTU.getHBaseAdmin().createTable(htd);
350 TableName toBeDisabledTable = TableName.valueOf(dropTable ? "droppedTable" : "disabledTable");
351 HTU.deleteTableIfAny(toBeDisabledTable);
352 htd = HTU.createTableDescriptor(toBeDisabledTable.toString());
353 htd.setRegionReplication(regionReplication);
354 HTU.getHBaseAdmin().createTable(htd);
355
356
357 ReplicationAdmin admin = new ReplicationAdmin(HTU.getConfiguration());
358 admin.disablePeer(ServerRegionReplicaUtil.getReplicationPeerId());
359
360
361
362 Connection connection = ConnectionFactory.createConnection(HTU.getConfiguration());
363 Table table = connection.getTable(tableName);
364 Table tableToBeDisabled = connection.getTable(toBeDisabledTable);
365
366 HTU.loadNumericRows(tableToBeDisabled, HBaseTestingUtility.fam1, 6000, 7000);
367
368 AtomicLong skippedEdits = new AtomicLong();
369 RegionReplicaReplicationEndpoint.RegionReplicaOutputSink sink =
370 mock(RegionReplicaReplicationEndpoint.RegionReplicaOutputSink.class);
371 when(sink.getSkippedEditsCounter()).thenReturn(skippedEdits);
372 RegionReplicaReplicationEndpoint.RegionReplicaSinkWriter sinkWriter =
373 new RegionReplicaReplicationEndpoint.RegionReplicaSinkWriter(sink,
374 (ClusterConnection) connection,
375 Executors.newSingleThreadExecutor(), Integer.MAX_VALUE);
376 RegionLocator rl = connection.getRegionLocator(toBeDisabledTable);
377 HRegionLocation hrl = rl.getRegionLocation(HConstants.EMPTY_BYTE_ARRAY);
378 byte[] encodedRegionName = hrl.getRegionInfo().getEncodedNameAsBytes();
379
380 Entry entry = new Entry(
381 new WALKey(encodedRegionName, toBeDisabledTable, 1),
382 new WALEdit());
383
384 HTU.getHBaseAdmin().disableTable(toBeDisabledTable);
385 if (dropTable) {
386 HTU.getHBaseAdmin().deleteTable(toBeDisabledTable);
387 }
388
389 sinkWriter.append(toBeDisabledTable, encodedRegionName,
390 HConstants.EMPTY_BYTE_ARRAY, Lists.newArrayList(entry, entry));
391
392 assertEquals(2, skippedEdits.get());
393
394 try {
395
396
397
398 HTU.loadNumericRows(table, HBaseTestingUtility.fam1, 0, 1000);
399
400
401 admin.enablePeer(ServerRegionReplicaUtil.getReplicationPeerId());
402
403 verifyReplication(tableName, regionReplication, 0, 1000);
404
405 } finally {
406 admin.close();
407 table.close();
408 rl.close();
409 tableToBeDisabled.close();
410 HTU.deleteTableIfAny(toBeDisabledTable);
411 connection.close();
412 }
413 }
414 }