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.apache.hadoop.hbase.HBaseTestingUtility.KEYS_FOR_HBA_CREATE_TABLE;
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assert.assertNotNull;
25 import static org.junit.Assert.assertNull;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assert.fail;
28 import com.google.common.collect.Lists;
29
30 import java.io.IOException;
31 import java.lang.reflect.Field;
32 import java.lang.reflect.Modifier;
33 import java.net.SocketTimeoutException;
34 import java.util.ArrayList;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Random;
39 import java.util.concurrent.ExecutorService;
40 import java.util.concurrent.SynchronousQueue;
41 import java.util.concurrent.ThreadPoolExecutor;
42 import java.util.concurrent.TimeUnit;
43 import java.util.concurrent.atomic.AtomicBoolean;
44 import java.util.concurrent.atomic.AtomicInteger;
45 import java.util.concurrent.atomic.AtomicLong;
46 import java.util.concurrent.atomic.AtomicReference;
47
48 import org.apache.commons.logging.Log;
49 import org.apache.commons.logging.LogFactory;
50 import org.apache.hadoop.conf.Configuration;
51 import org.apache.hadoop.hbase.CategoryBasedTimeout;
52 import org.apache.hadoop.hbase.Cell;
53 import org.apache.hadoop.hbase.HBaseConfiguration;
54 import org.apache.hadoop.hbase.HBaseTestingUtility;
55 import org.apache.hadoop.hbase.HConstants;
56 import org.apache.hadoop.hbase.HRegionLocation;
57 import org.apache.hadoop.hbase.HTableDescriptor;
58 import org.apache.hadoop.hbase.RegionLocations;
59 import org.apache.hadoop.hbase.ServerName;
60 import org.apache.hadoop.hbase.TableName;
61 import org.apache.hadoop.hbase.Waiter;
62 import org.apache.hadoop.hbase.client.ConnectionManager.HConnectionImplementation;
63 import org.apache.hadoop.hbase.coprocessor.BaseRegionObserver;
64 import org.apache.hadoop.hbase.coprocessor.ObserverContext;
65 import org.apache.hadoop.hbase.coprocessor.RegionCoprocessorEnvironment;
66 import org.apache.hadoop.hbase.exceptions.ClientExceptionsUtil;
67 import org.apache.hadoop.hbase.exceptions.DeserializationException;
68 import org.apache.hadoop.hbase.exceptions.RegionMovedException;
69 import org.apache.hadoop.hbase.filter.Filter;
70 import org.apache.hadoop.hbase.filter.FilterBase;
71 import org.apache.hadoop.hbase.ipc.CallTimeoutException;
72 import org.apache.hadoop.hbase.ipc.RpcClient;
73 import org.apache.hadoop.hbase.ipc.RpcControllerFactory;
74 import org.apache.hadoop.hbase.master.HMaster;
75 import org.apache.hadoop.hbase.regionserver.HRegionServer;
76 import org.apache.hadoop.hbase.regionserver.Region;
77 import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;
78 import org.apache.hadoop.hbase.regionserver.wal.WALEdit;
79 import org.apache.hadoop.hbase.testclassification.LargeTests;
80 import org.apache.hadoop.hbase.util.Bytes;
81 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
82 import org.apache.hadoop.hbase.util.JVMClusterUtil;
83 import org.apache.hadoop.hbase.util.ManualEnvironmentEdge;
84 import org.apache.hadoop.hbase.util.Threads;
85 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
86 import org.junit.AfterClass;
87 import org.junit.Assert;
88 import org.junit.BeforeClass;
89 import org.junit.Ignore;
90 import org.junit.Rule;
91 import org.junit.Test;
92 import org.junit.experimental.categories.Category;
93 import org.junit.rules.TestRule;
94
95 import static org.junit.Assert.assertEquals;
96 import static org.junit.Assert.assertFalse;
97 import static org.junit.Assert.assertNotNull;
98 import static org.junit.Assert.assertNull;
99 import static org.junit.Assert.assertTrue;
100 import static org.junit.Assert.fail;
101
102
103
104
105 @Category({LargeTests.class})
106 public class TestHCM {
107 @Rule public final TestRule timeout = CategoryBasedTimeout.builder()
108 .withTimeout(this.getClass())
109 .withLookingForStuckThread(true)
110 .build();
111 private static final Log LOG = LogFactory.getLog(TestHCM.class);
112 private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
113 private static final TableName TABLE_NAME =
114 TableName.valueOf("test");
115 private static final TableName TABLE_NAME1 =
116 TableName.valueOf("test1");
117 private static final TableName TABLE_NAME2 =
118 TableName.valueOf("test2");
119 private static final TableName TABLE_NAME3 =
120 TableName.valueOf("test3");
121 private static final TableName TABLE_NAME4 =
122 TableName.valueOf("test4");
123 private static final byte[] FAM_NAM = Bytes.toBytes("f");
124 private static final byte[] ROW = Bytes.toBytes("bbb");
125 private static final byte[] ROW_X = Bytes.toBytes("xxx");
126 private static Random _randy = new Random();
127 private static final int RPC_RETRY = 5;
128
129
130
131
132 public static class SleepAndFailFirstTime extends BaseRegionObserver {
133 static final AtomicLong ct = new AtomicLong(0);
134 static final String SLEEP_TIME_CONF_KEY =
135 "hbase.coprocessor.SleepAndFailFirstTime.sleepTime";
136 static final long DEFAULT_SLEEP_TIME = 20000;
137 static final AtomicLong sleepTime = new AtomicLong(DEFAULT_SLEEP_TIME);
138
139 public SleepAndFailFirstTime() {
140 }
141
142 @Override
143 public void postOpen(ObserverContext<RegionCoprocessorEnvironment> c) {
144 RegionCoprocessorEnvironment env = c.getEnvironment();
145 Configuration conf = env.getConfiguration();
146 sleepTime.set(conf.getLong(SLEEP_TIME_CONF_KEY, DEFAULT_SLEEP_TIME));
147 }
148
149 @Override
150 public void preGetOp(final ObserverContext<RegionCoprocessorEnvironment> e,
151 final Get get, final List<Cell> results) throws IOException {
152 Threads.sleep(sleepTime.get());
153 if (ct.incrementAndGet() == 1) {
154 throw new IOException("first call I fail");
155 }
156 }
157
158 @Override
159 public void prePut(final ObserverContext<RegionCoprocessorEnvironment> e,
160 final Put put, final WALEdit edit, final Durability durability) throws IOException {
161 Threads.sleep(sleepTime.get());
162 if (ct.incrementAndGet() == 1) {
163 throw new IOException("first call I fail");
164 }
165 }
166
167 @Override
168 public void preDelete(final ObserverContext<RegionCoprocessorEnvironment> e,
169 final Delete delete,
170 final WALEdit edit, final Durability durability) throws IOException {
171 Threads.sleep(sleepTime.get());
172 if (ct.incrementAndGet() == 1) {
173 throw new IOException("first call I fail");
174 }
175 }
176
177 @Override
178 public Result preIncrement(final ObserverContext<RegionCoprocessorEnvironment> e,
179 final Increment increment) throws IOException {
180 Threads.sleep(sleepTime.get());
181 if (ct.incrementAndGet() == 1) {
182 throw new IOException("first call I fail");
183 }
184 return super.preIncrement(e, increment);
185 }
186
187 }
188
189 public static class SleepCoprocessor extends BaseRegionObserver {
190 public static final int SLEEP_TIME = 5000;
191 @Override
192 public void preGetOp(final ObserverContext<RegionCoprocessorEnvironment> e,
193 final Get get, final List<Cell> results) throws IOException {
194 Threads.sleep(SLEEP_TIME);
195 }
196
197 @Override
198 public Result preIncrement(final ObserverContext<RegionCoprocessorEnvironment> e,
199 final Increment increment) throws IOException {
200 Threads.sleep(SLEEP_TIME);
201 return super.preIncrement(e, increment);
202 }
203
204 @Override
205 public void preDelete(final ObserverContext<RegionCoprocessorEnvironment> e, final Delete delete,
206 final WALEdit edit, final Durability durability) throws IOException {
207 Threads.sleep(SLEEP_TIME);
208 }
209
210 @Override
211 public void prePut(final ObserverContext<RegionCoprocessorEnvironment> e,
212 final Put put, final WALEdit edit, final Durability durability) throws IOException {
213 Threads.sleep(SLEEP_TIME);
214 }
215
216 }
217
218 public static class SleepLongerAtFirstCoprocessor extends BaseRegionObserver {
219 public static final int SLEEP_TIME = 2000;
220 static final AtomicLong ct = new AtomicLong(0);
221
222 @Override
223 public void preGetOp(final ObserverContext<RegionCoprocessorEnvironment> e,
224 final Get get, final List<Cell> results) throws IOException {
225
226
227
228 if (ct.incrementAndGet() <= 1) {
229 Threads.sleep(SLEEP_TIME * (RPC_RETRY-1) * 2);
230 } else {
231 Threads.sleep(SLEEP_TIME);
232 }
233 }
234 }
235
236 @BeforeClass
237 public static void setUpBeforeClass() throws Exception {
238 TEST_UTIL.getConfiguration().setBoolean(HConstants.STATUS_PUBLISHED, true);
239
240 TEST_UTIL.getConfiguration().setInt(HConstants.REGION_SERVER_HIGH_PRIORITY_HANDLER_COUNT, 10);
241 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, RPC_RETRY);
242
243 TEST_UTIL.getConfiguration().setInt(HConstants.REGION_SERVER_HANDLER_COUNT, 1);
244 TEST_UTIL.startMiniCluster(2);
245 }
246
247 @AfterClass public static void tearDownAfterClass() throws Exception {
248 TEST_UTIL.shutdownMiniCluster();
249 }
250
251
252 private static int getHConnectionManagerCacheSize(){
253 return HConnectionTestingUtility.getConnectionCount();
254 }
255
256 @Test
257 public void testClusterConnection() throws IOException {
258 ThreadPoolExecutor otherPool = new ThreadPoolExecutor(1, 1,
259 5, TimeUnit.SECONDS,
260 new SynchronousQueue<Runnable>(),
261 Threads.newDaemonThreadFactory("test-hcm"));
262
263 HConnection con1 = HConnectionManager.createConnection(TEST_UTIL.getConfiguration());
264 HConnection con2 = HConnectionManager.createConnection(TEST_UTIL.getConfiguration(), otherPool);
265
266 assertTrue(otherPool == ((HConnectionImplementation)con2).getCurrentBatchPool());
267
268 String tableName = "testClusterConnection";
269 TEST_UTIL.createTable(tableName.getBytes(), FAM_NAM).close();
270 HTable t = (HTable)con1.getTable(tableName, otherPool);
271
272 assertNull("Internal Thread pool should be null", ((HConnectionImplementation)con1).getCurrentBatchPool());
273
274 assertTrue(otherPool == t.getPool());
275 t.close();
276
277 t = (HTable)con2.getTable(tableName);
278
279 assertTrue(otherPool == t.getPool());
280 t.close();
281
282 t = (HTable)con2.getTable(Bytes.toBytes(tableName));
283
284 assertTrue(otherPool == t.getPool());
285 t.close();
286
287 t = (HTable)con2.getTable(TableName.valueOf(tableName));
288
289 assertTrue(otherPool == t.getPool());
290 t.close();
291
292 t = (HTable)con1.getTable(tableName);
293 ExecutorService pool = ((HConnectionImplementation)con1).getCurrentBatchPool();
294
295 assertNotNull("An internal Thread pool should have been created", pool);
296
297 assertTrue(t.getPool() == pool);
298 t.close();
299
300 t = (HTable)con1.getTable(tableName);
301
302 assertTrue(t.getPool() == pool);
303 t.close();
304
305 con1.close();
306
307 assertTrue(pool.isShutdown());
308
309 con2.close();
310
311 assertFalse(otherPool.isShutdown());
312 otherPool.shutdownNow();
313 }
314
315
316
317
318
319 @Test
320 public void testAdminFactory() throws IOException {
321 Connection con1 = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
322 Admin admin = con1.getAdmin();
323 assertTrue(admin.getConnection() == con1);
324 assertTrue(admin.getConfiguration() == TEST_UTIL.getConfiguration());
325 con1.close();
326 }
327
328
329 @Ignore @Test (expected = RegionServerStoppedException.class)
330 public void testClusterStatus() throws Exception {
331
332 TableName tn =
333 TableName.valueOf("testClusterStatus");
334 byte[] cf = "cf".getBytes();
335 byte[] rk = "rk1".getBytes();
336
337 JVMClusterUtil.RegionServerThread rs = TEST_UTIL.getHBaseCluster().startRegionServer();
338 rs.waitForServerOnline();
339 final ServerName sn = rs.getRegionServer().getServerName();
340
341 HTable t = TEST_UTIL.createTable(tn, cf);
342 TEST_UTIL.waitTableAvailable(tn);
343 TEST_UTIL.waitUntilNoRegionsInTransition();
344
345 final HConnectionImplementation hci = (HConnectionImplementation)t.getConnection();
346 while (t.getRegionLocation(rk).getPort() != sn.getPort()){
347 TEST_UTIL.getHBaseAdmin().move(t.getRegionLocation(rk).getRegionInfo().
348 getEncodedNameAsBytes(), Bytes.toBytes(sn.toString()));
349 TEST_UTIL.waitUntilNoRegionsInTransition();
350 hci.clearRegionCache(tn);
351 }
352 Assert.assertNotNull(hci.clusterStatusListener);
353 TEST_UTIL.assertRegionOnServer(t.getRegionLocation(rk).getRegionInfo(), sn, 20000);
354
355 Put p1 = new Put(rk);
356 p1.add(cf, "qual".getBytes(), "val".getBytes());
357 t.put(p1);
358
359 rs.getRegionServer().abort("I'm dead");
360
361
362 TEST_UTIL.waitFor(40000, 1000, true, new Waiter.Predicate<Exception>() {
363 @Override
364 public boolean evaluate() throws Exception {
365 return TEST_UTIL.getHBaseCluster().getMaster().getServerManager().
366 getDeadServers().isDeadServer(sn);
367 }
368 });
369
370 TEST_UTIL.waitFor(40000, 1000, true, new Waiter.Predicate<Exception>() {
371 @Override
372 public boolean evaluate() throws Exception {
373 return hci.clusterStatusListener.isDeadServer(sn);
374 }
375 });
376
377 t.close();
378 hci.getClient(sn);
379 }
380
381
382
383
384
385 @Test
386 public void testConnectionCloseAllowsInterrupt() throws Exception {
387 testConnectionClose(true);
388 }
389
390 @Test
391 public void testConnectionNotAllowsInterrupt() throws Exception {
392 testConnectionClose(false);
393 }
394
395
396
397
398
399
400
401
402
403 @Test
404 public void testGetOperationTimeout() throws Exception {
405 HTableDescriptor hdt = TEST_UTIL.createTableDescriptor("HCM-testGetOperationTimeout");
406 hdt.addCoprocessor(SleepAndFailFirstTime.class.getName());
407 Table table = TEST_UTIL.createTable(hdt, new byte[][]{FAM_NAM}, TEST_UTIL.getConfiguration());
408 table.setRpcTimeout(Integer.MAX_VALUE);
409 SleepAndFailFirstTime.ct.set(0);
410
411 table.setOperationTimeout(120 * 1000);
412 table.get(new Get(FAM_NAM));
413
414
415 SleepAndFailFirstTime.ct.set(0);
416 try {
417 table.setOperationTimeout(30 * 1000);
418 table.get(new Get(FAM_NAM));
419 Assert.fail("We expect an exception here");
420 } catch (SocketTimeoutException e) {
421
422
423
424 LOG.info("We received an exception, as expected ", e);
425 } catch (IOException e) {
426 Assert.fail("Wrong exception:" + e.getMessage());
427 } finally {
428 table.close();
429 }
430 }
431
432 @Test
433 public void testPutOperationTimeout() throws Exception {
434 HTableDescriptor hdt = TEST_UTIL.createTableDescriptor("HCM-testPutOperationTimeout");
435 hdt.addCoprocessor(SleepAndFailFirstTime.class.getName());
436 Table table = TEST_UTIL.createTable(hdt, new byte[][] { FAM_NAM },TEST_UTIL.getConfiguration());
437 table.setRpcTimeout(Integer.MAX_VALUE);
438 SleepAndFailFirstTime.ct.set(0);
439
440 table.setOperationTimeout(120 * 1000);
441 table.put(new Put(FAM_NAM).addColumn(FAM_NAM, FAM_NAM, FAM_NAM));
442
443
444 SleepAndFailFirstTime.ct.set(0);
445 try {
446 table.setOperationTimeout(30 * 1000);
447 table.put(new Put(FAM_NAM).addColumn(FAM_NAM, FAM_NAM, FAM_NAM));
448 Assert.fail("We expect an exception here");
449 } catch (RetriesExhaustedWithDetailsException e) {
450
451
452
453 LOG.info("We received an exception, as expected ", e);
454 } catch (IOException e) {
455 Assert.fail("Wrong exception:" + e.getMessage());
456 } finally {
457 table.close();
458 }
459 }
460
461 @Test
462 public void testDeleteOperationTimeout() throws Exception {
463 HTableDescriptor hdt = TEST_UTIL.createTableDescriptor("HCM-testDeleteOperationTimeout");
464 hdt.addCoprocessor(SleepAndFailFirstTime.class.getName());
465 Table table = TEST_UTIL.createTable(hdt, new byte[][] { FAM_NAM },TEST_UTIL.getConfiguration());
466 table.setRpcTimeout(Integer.MAX_VALUE);
467 SleepAndFailFirstTime.ct.set(0);
468
469 table.setOperationTimeout(120 * 1000);
470 table.delete(new Delete(FAM_NAM));
471
472
473 SleepAndFailFirstTime.ct.set(0);
474 try {
475 table.setOperationTimeout(30 * 1000);
476 table.delete(new Delete(FAM_NAM));
477 Assert.fail("We expect an exception here");
478 } catch (IOException e) {
479
480
481
482 LOG.info("We received an exception, as expected ", e);
483 } finally {
484 table.close();
485 }
486 }
487 @Test
488 public void testDeleteRpcTimeout() throws Exception {
489 HTableDescriptor hdt = TEST_UTIL.createTableDescriptor("HCM-testDeleteRpcTimeout");
490 hdt.addCoprocessor(SleepCoprocessor.class.getName());
491 Configuration c = new Configuration(TEST_UTIL.getConfiguration());
492
493 try (Table t = TEST_UTIL.createTable(hdt, new byte[][] { FAM_NAM }, c)) {
494 t.setRpcTimeout(SleepCoprocessor.SLEEP_TIME / 2);
495 t.setOperationTimeout(SleepCoprocessor.SLEEP_TIME * 100);
496 Delete d = new Delete(FAM_NAM);
497 d.addColumn(FAM_NAM, FAM_NAM, 1);
498 t.delete(d);
499 fail("Write should not have succeeded");
500 } catch (RetriesExhaustedException e) {
501
502 }
503
504 }
505
506 @Test
507 public void testPutRpcTimeout() throws Exception {
508 HTableDescriptor hdt = TEST_UTIL.createTableDescriptor("HCM-testPutRpcTimeout");
509 hdt.addCoprocessor(SleepCoprocessor.class.getName());
510 Configuration c = new Configuration(TEST_UTIL.getConfiguration());
511
512 try (Table t = TEST_UTIL.createTable(hdt, new byte[][] { FAM_NAM }, c)) {
513 t.setRpcTimeout(SleepCoprocessor.SLEEP_TIME / 2);
514 t.setOperationTimeout(SleepCoprocessor.SLEEP_TIME * 100);
515 Put p = new Put(FAM_NAM);
516 p.addColumn(FAM_NAM, FAM_NAM, FAM_NAM);
517 t.put(p);
518 fail("Write should not have succeeded");
519 } catch (IOException e) {
520
521 }
522
523 }
524
525 @Test(expected = RetriesExhaustedException.class)
526 public void testRpcTimeout() throws Exception {
527 HTableDescriptor hdt = TEST_UTIL.createTableDescriptor("HCM-testRpcTimeout");
528 hdt.addCoprocessor(SleepCoprocessor.class.getName());
529 Configuration c = new Configuration(TEST_UTIL.getConfiguration());
530
531 try (Table t = TEST_UTIL.createTable(hdt, new byte[][] { FAM_NAM }, c)) {
532 assert t instanceof HTable;
533 HTable table = (HTable) t;
534 table.setRpcTimeout(SleepCoprocessor.SLEEP_TIME / 2);
535 table.setOperationTimeout(SleepCoprocessor.SLEEP_TIME * 100);
536 table.get(new Get(FAM_NAM));
537 }
538 }
539
540 @Test
541 public void testDropTimeoutRequest() throws Exception {
542
543
544
545
546 HTableDescriptor hdt = TEST_UTIL.createTableDescriptor("HCM-testDropTimeputRequest");
547 hdt.addCoprocessor(SleepLongerAtFirstCoprocessor.class.getName());
548 Configuration c = new Configuration(TEST_UTIL.getConfiguration());
549 try (Table t = TEST_UTIL.createTable(hdt, new byte[][] { FAM_NAM }, c)) {
550 t.setRpcTimeout(SleepLongerAtFirstCoprocessor.SLEEP_TIME * 2);
551 t.get(new Get(FAM_NAM));
552 }
553 }
554
555
556
557
558 @Test
559 public void testRpcRetryingCallerSleep() throws Exception {
560 HTableDescriptor hdt = TEST_UTIL.createTableDescriptor("HCM-testRpcRetryingCallerSleep");
561 hdt.addCoprocessorWithSpec("|" + SleepAndFailFirstTime.class.getName() + "||"
562 + SleepAndFailFirstTime.SLEEP_TIME_CONF_KEY + "=2000");
563 TEST_UTIL.createTable(hdt, new byte[][] { FAM_NAM }).close();
564
565 Configuration c = new Configuration(TEST_UTIL.getConfiguration());
566 SleepAndFailFirstTime.ct.set(0);
567 c.setInt(HConstants.HBASE_CLIENT_PAUSE, 3000);
568 c.setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 4000);
569
570 Connection connection = ConnectionFactory.createConnection(c);
571 Table t = connection.getTable(TableName.valueOf("HCM-testRpcRetryingCallerSleep"));
572 if (t instanceof HTable) {
573 HTable table = (HTable) t;
574 table.setOperationTimeout(8000);
575
576 table.get(new Get(FAM_NAM));
577
578
579 SleepAndFailFirstTime.ct.set(0);
580 try {
581 table.setOperationTimeout(6000);
582
583
584 table.get(new Get(FAM_NAM));
585 Assert.fail("We expect an exception here");
586 } catch (SocketTimeoutException e) {
587 LOG.info("We received an exception, as expected ", e);
588 } catch (IOException e) {
589 Assert.fail("Wrong exception:" + e.getMessage());
590 } finally {
591 table.close();
592 connection.close();
593 }
594 }
595 }
596
597 @Test
598 public void testCallableSleep() throws Exception {
599 long pauseTime;
600 long baseTime = 100;
601 TableName tableName = TableName.valueOf("HCM-testCallableSleep");
602 HTable table = TEST_UTIL.createTable(tableName, FAM_NAM);
603 RegionServerCallable<Object> regionServerCallable = new RegionServerCallable<Object>(
604 TEST_UTIL.getConnection(), tableName, ROW) {
605 public Object call(int timeout) throws IOException {
606 return null;
607 }
608 };
609
610 regionServerCallable.prepare(false);
611 for (int i = 0; i < HConstants.RETRY_BACKOFF.length; i++) {
612 pauseTime = regionServerCallable.sleep(baseTime, i);
613 assertTrue(pauseTime >= (baseTime * HConstants.RETRY_BACKOFF[i]));
614 assertTrue(pauseTime <= (baseTime * HConstants.RETRY_BACKOFF[i] * 1.01f));
615 }
616
617 RegionAdminServiceCallable<Object> regionAdminServiceCallable =
618 new RegionAdminServiceCallable<Object>(
619 (ClusterConnection) TEST_UTIL.getConnection(), new RpcControllerFactory(
620 TEST_UTIL.getConfiguration()), tableName, ROW) {
621 public Object call(int timeout) throws IOException {
622 return null;
623 }
624 };
625
626 regionAdminServiceCallable.prepare(false);
627 for (int i = 0; i < HConstants.RETRY_BACKOFF.length; i++) {
628 pauseTime = regionAdminServiceCallable.sleep(baseTime, i);
629 assertTrue(pauseTime >= (baseTime * HConstants.RETRY_BACKOFF[i]));
630 assertTrue(pauseTime <= (baseTime * HConstants.RETRY_BACKOFF[i] * 1.01f));
631 }
632
633 MasterCallable masterCallable = new MasterCallable((HConnection) TEST_UTIL.getConnection()) {
634 public Object call(int timeout) throws IOException {
635 return null;
636 }
637 };
638
639 for (int i = 0; i < HConstants.RETRY_BACKOFF.length; i++) {
640 pauseTime = masterCallable.sleep(baseTime, i);
641 assertTrue(pauseTime >= (baseTime * HConstants.RETRY_BACKOFF[i]));
642 assertTrue(pauseTime <= (baseTime * HConstants.RETRY_BACKOFF[i] * 1.01f));
643 }
644 }
645
646 private void testConnectionClose(boolean allowsInterrupt) throws Exception {
647 TableName tableName = TableName.valueOf("HCM-testConnectionClose" + allowsInterrupt);
648 TEST_UTIL.createTable(tableName, FAM_NAM).close();
649
650 boolean previousBalance = TEST_UTIL.getHBaseAdmin().setBalancerRunning(false, true);
651
652 Configuration c2 = new Configuration(TEST_UTIL.getConfiguration());
653
654 c2.set(HConstants.HBASE_CLIENT_INSTANCE_ID, String.valueOf(-1));
655 c2.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 100);
656 c2.setInt(HConstants.HBASE_CLIENT_PAUSE, 1);
657 c2.setInt(RpcClient.FAILED_SERVER_EXPIRY_KEY, 0);
658 c2.setBoolean(RpcClient.SPECIFIC_WRITE_THREAD, allowsInterrupt);
659
660 final HTable table = new HTable(c2, tableName);
661
662 Put put = new Put(ROW);
663 put.add(FAM_NAM, ROW, ROW);
664 table.put(put);
665
666
667 final AtomicInteger step = new AtomicInteger(0);
668
669 final AtomicReference<Throwable> failed = new AtomicReference<Throwable>(null);
670 Thread t = new Thread("testConnectionCloseThread") {
671 @Override
672 public void run() {
673 int done = 0;
674 try {
675 step.set(1);
676 while (step.get() == 1) {
677 Get get = new Get(ROW);
678 table.get(get);
679 done++;
680 if (done % 100 == 0)
681 LOG.info("done=" + done);
682 }
683 } catch (Throwable t) {
684 failed.set(t);
685 LOG.error(t);
686 }
687 step.set(3);
688 }
689 };
690 t.start();
691 TEST_UTIL.waitFor(20000, new Waiter.Predicate<Exception>() {
692 @Override
693 public boolean evaluate() throws Exception {
694 return step.get() == 1;
695 }
696 });
697
698 ServerName sn = table.getRegionLocation(ROW).getServerName();
699 ConnectionManager.HConnectionImplementation conn =
700 (ConnectionManager.HConnectionImplementation) table.getConnection();
701 RpcClient rpcClient = conn.getRpcClient();
702
703 LOG.info("Going to cancel connections. connection=" + conn.toString() + ", sn=" + sn);
704 for (int i = 0; i < 5000; i++) {
705 rpcClient.cancelConnections(sn);
706 Thread.sleep(5);
707 }
708
709 step.compareAndSet(1, 2);
710
711
712 TEST_UTIL.waitFor(40000, new Waiter.Predicate<Exception>() {
713 @Override
714 public boolean evaluate() throws Exception {
715 return step.get() == 3;
716 }
717 });
718 table.close();
719 Assert.assertTrue("Unexpected exception is " + failed.get(), failed.get() == null);
720 TEST_UTIL.getHBaseAdmin().setBalancerRunning(previousBalance, true);
721 }
722
723
724
725
726 @Test
727 public void testConnectionIdle() throws Exception {
728 TableName tableName = TableName.valueOf("HCM-testConnectionIdle");
729 TEST_UTIL.createTable(tableName, FAM_NAM).close();
730 int idleTime = 20000;
731 boolean previousBalance = TEST_UTIL.getHBaseAdmin().setBalancerRunning(false, true);
732
733 Configuration c2 = new Configuration(TEST_UTIL.getConfiguration());
734
735 c2.set(HConstants.HBASE_CLIENT_INSTANCE_ID, String.valueOf(-1));
736 c2.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1);
737 c2.setInt(RpcClient.IDLE_TIME, idleTime);
738
739 final Table table = new HTable(c2, tableName);
740
741 Put put = new Put(ROW);
742 put.add(FAM_NAM, ROW, ROW);
743 table.put(put);
744
745 ManualEnvironmentEdge mee = new ManualEnvironmentEdge();
746 mee.setValue(System.currentTimeMillis());
747 EnvironmentEdgeManager.injectEdge(mee);
748 LOG.info("first get");
749 table.get(new Get(ROW));
750
751 LOG.info("first get - changing the time & sleeping");
752 mee.incValue(idleTime + 1000);
753 Thread.sleep(1500);
754
755
756 LOG.info("second get - connection has been marked idle in the middle");
757
758
759 table.get(new Get(ROW));
760 mee.incValue(idleTime + 1000);
761
762 LOG.info("third get - connection is idle, but the reader doesn't know yet");
763
764
765
766
767
768
769
770 table.get(new Get(ROW));
771
772 LOG.info("we're done - time will change back");
773
774 table.close();
775 EnvironmentEdgeManager.reset();
776 TEST_UTIL.getHBaseAdmin().setBalancerRunning(previousBalance, true);
777 }
778
779
780
781
782
783
784 @Test
785 public void testConnectionCut() throws Exception {
786
787 TableName tableName = TableName.valueOf("HCM-testConnectionCut");
788
789 TEST_UTIL.createTable(tableName, FAM_NAM).close();
790 boolean previousBalance = TEST_UTIL.getHBaseAdmin().setBalancerRunning(false, true);
791
792 Configuration c2 = new Configuration(TEST_UTIL.getConfiguration());
793
794 c2.set(HConstants.HBASE_CLIENT_INSTANCE_ID, String.valueOf(-1));
795 c2.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1);
796 c2.setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 30 * 1000);
797
798 HTable table = new HTable(c2, tableName);
799
800 Put p = new Put(FAM_NAM);
801 p.add(FAM_NAM, FAM_NAM, FAM_NAM);
802 table.put(p);
803
804 final HConnectionImplementation hci = (HConnectionImplementation)table.getConnection();
805 final HRegionLocation loc = table.getRegionLocation(FAM_NAM);
806
807 Get get = new Get(FAM_NAM);
808 Assert.assertNotNull(table.get(get));
809
810 get = new Get(FAM_NAM);
811 get.setFilter(new BlockingFilter());
812
813
814 Thread t = new Thread() {
815 @Override
816 public void run() {
817 synchronized (syncBlockingFilter) {
818 try {
819 syncBlockingFilter.wait();
820 } catch (InterruptedException e) {
821 throw new RuntimeException(e);
822 }
823 }
824 hci.clusterStatusListener.deadServerHandler.newDead(loc.getServerName());
825 }
826 };
827
828 t.start();
829 try {
830 table.get(get);
831 Assert.fail();
832 } catch (IOException expected) {
833 LOG.debug("Received: " + expected);
834 Assert.assertFalse(expected instanceof SocketTimeoutException);
835 Assert.assertFalse(syncBlockingFilter.get());
836 } finally {
837 syncBlockingFilter.set(true);
838 t.join();
839 HConnectionManager.getConnection(c2).close();
840 TEST_UTIL.getHBaseAdmin().setBalancerRunning(previousBalance, true);
841 }
842
843 table.close();
844 }
845
846 protected static final AtomicBoolean syncBlockingFilter = new AtomicBoolean(false);
847
848 public static class BlockingFilter extends FilterBase {
849 @Override
850 public boolean filterRowKey(byte[] buffer, int offset, int length) throws IOException {
851 int i = 0;
852 while (i++ < 1000 && !syncBlockingFilter.get()) {
853 synchronized (syncBlockingFilter) {
854 syncBlockingFilter.notifyAll();
855 }
856 Threads.sleep(100);
857 }
858 syncBlockingFilter.set(true);
859 return false;
860 }
861 @Override
862 public ReturnCode filterKeyValue(Cell ignored) throws IOException {
863 return ReturnCode.INCLUDE;
864 }
865
866 public static Filter parseFrom(final byte [] pbBytes) throws DeserializationException{
867 return new BlockingFilter();
868 }
869 }
870
871 @Test (timeout=120000)
872 public void abortingHConnectionRemovesItselfFromHCM() throws Exception {
873
874 Map<HConnectionKey, HConnectionImplementation> oldHBaseInstances =
875 new HashMap<HConnectionKey, HConnectionImplementation>();
876 oldHBaseInstances.putAll(ConnectionManager.CONNECTION_INSTANCES);
877
878 ConnectionManager.CONNECTION_INSTANCES.clear();
879
880 try {
881 HConnection connection = HConnectionManager.getConnection(TEST_UTIL.getConfiguration());
882 connection.abort("test abortingHConnectionRemovesItselfFromHCM", new Exception(
883 "test abortingHConnectionRemovesItselfFromHCM"));
884 Assert.assertNotSame(connection,
885 HConnectionManager.getConnection(TEST_UTIL.getConfiguration()));
886 } finally {
887
888 ConnectionManager.CONNECTION_INSTANCES.clear();
889 ConnectionManager.CONNECTION_INSTANCES.putAll(oldHBaseInstances);
890 }
891 }
892
893
894
895
896
897
898 @Test
899 public void testRegionCaching() throws Exception{
900 TEST_UTIL.createMultiRegionTable(TABLE_NAME, FAM_NAM).close();
901 Configuration conf = new Configuration(TEST_UTIL.getConfiguration());
902 conf.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1);
903 HTable table = new HTable(conf, TABLE_NAME);
904
905 TEST_UTIL.waitUntilAllRegionsAssigned(table.getName());
906 Put put = new Put(ROW);
907 put.add(FAM_NAM, ROW, ROW);
908 table.put(put);
909 ConnectionManager.HConnectionImplementation conn =
910 (ConnectionManager.HConnectionImplementation)table.getConnection();
911
912 assertNotNull(conn.getCachedLocation(TABLE_NAME, ROW));
913
914 final int nextPort = conn.getCachedLocation(TABLE_NAME, ROW).getRegionLocation().getPort() + 1;
915 HRegionLocation loc = conn.getCachedLocation(TABLE_NAME, ROW).getRegionLocation();
916 conn.updateCachedLocation(loc.getRegionInfo(), loc.getServerName(),
917 ServerName.valueOf("127.0.0.1", nextPort,
918 HConstants.LATEST_TIMESTAMP), HConstants.LATEST_TIMESTAMP);
919 Assert.assertEquals(conn.getCachedLocation(TABLE_NAME, ROW)
920 .getRegionLocation().getPort(), nextPort);
921
922 conn.clearRegionCache(TABLE_NAME, ROW.clone());
923 RegionLocations rl = conn.getCachedLocation(TABLE_NAME, ROW);
924 assertNull("What is this location?? " + rl, rl);
925
926
927 conn.clearRegionCache(TABLE_NAME);
928 conn.getRegionLocator(TABLE_NAME).getAllRegionLocations();
929 assertNotNull("Can't get cached location for row aaa",
930 conn.getCachedLocation(TABLE_NAME,Bytes.toBytes("aaa")));
931 for(byte[] startKey:KEYS_FOR_HBA_CREATE_TABLE){
932 assertNotNull("Can't get cached location for row "+
933 Bytes.toString(startKey),conn.getCachedLocation(TABLE_NAME,startKey));
934 }
935
936
937 conn.clearRegionCache(TABLE_NAME);
938 Assert.assertEquals(0, conn.getNumberOfCachedRegionLocations(TABLE_NAME));
939 Put put2 = new Put(ROW);
940 put2.add(FAM_NAM, ROW, ROW);
941 table.put(put2);
942 assertNotNull(conn.getCachedLocation(TABLE_NAME, ROW));
943 assertNotNull(conn.getCachedLocation(TableName.valueOf(TABLE_NAME.getName()), ROW.clone()));
944
945 TEST_UTIL.getHBaseAdmin().setBalancerRunning(false, false);
946 HMaster master = TEST_UTIL.getMiniHBaseCluster().getMaster();
947
948
949 TEST_UTIL.waitUntilNoRegionsInTransition();
950
951
952 HRegionLocation toMove = conn.getCachedLocation(TABLE_NAME, ROW).getRegionLocation();
953 byte[] regionName = toMove.getRegionInfo().getRegionName();
954 byte[] encodedRegionNameBytes = toMove.getRegionInfo().getEncodedNameAsBytes();
955
956
957 int curServerId = TEST_UTIL.getHBaseCluster().getServerWith(regionName);
958 int destServerId = (curServerId == 0 ? 1 : 0);
959
960 HRegionServer curServer = TEST_UTIL.getHBaseCluster().getRegionServer(curServerId);
961 HRegionServer destServer = TEST_UTIL.getHBaseCluster().getRegionServer(destServerId);
962
963 ServerName destServerName = destServer.getServerName();
964
965
966 Assert.assertTrue(curServer != destServer);
967 Assert.assertFalse(curServer.getServerName().equals(destServer.getServerName()));
968 Assert.assertFalse( toMove.getPort() == destServerName.getPort());
969 Assert.assertNotNull(curServer.getOnlineRegion(regionName));
970 Assert.assertNull(destServer.getOnlineRegion(regionName));
971 Assert.assertFalse(TEST_UTIL.getMiniHBaseCluster().getMaster().
972 getAssignmentManager().getRegionStates().isRegionsInTransition());
973
974
975
976 LOG.info("Move starting region="+toMove.getRegionInfo().getRegionNameAsString());
977 TEST_UTIL.getHBaseAdmin().move(
978 toMove.getRegionInfo().getEncodedNameAsBytes(),
979 destServerName.getServerName().getBytes()
980 );
981
982 while (destServer.getOnlineRegion(regionName) == null ||
983 destServer.getRegionsInTransitionInRS().containsKey(encodedRegionNameBytes) ||
984 curServer.getRegionsInTransitionInRS().containsKey(encodedRegionNameBytes) ||
985 master.getAssignmentManager().getRegionStates().isRegionsInTransition()) {
986
987 Thread.sleep(1);
988 }
989
990 LOG.info("Move finished for region="+toMove.getRegionInfo().getRegionNameAsString());
991
992
993 Assert.assertNull(curServer.getOnlineRegion(regionName));
994 Assert.assertNotNull(destServer.getOnlineRegion(regionName));
995 Assert.assertFalse(destServer.getRegionsInTransitionInRS().containsKey(encodedRegionNameBytes));
996 Assert.assertFalse(curServer.getRegionsInTransitionInRS().containsKey(encodedRegionNameBytes));
997
998
999
1000 Assert.assertFalse(
1001 conn.getCachedLocation(TABLE_NAME, ROW).getRegionLocation()
1002 .getPort() == destServerName.getPort());
1003
1004
1005
1006 LOG.info("Put starting");
1007 Put put3 = new Put(ROW);
1008 put3.add(FAM_NAM, ROW, ROW);
1009 try {
1010 table.put(put3);
1011 Assert.fail("Unreachable point");
1012 } catch (RetriesExhaustedWithDetailsException e){
1013 LOG.info("Put done, exception caught: " + e.getClass());
1014 Assert.assertEquals(1, e.getNumExceptions());
1015 Assert.assertEquals(1, e.getCauses().size());
1016 Assert.assertArrayEquals(e.getRow(0).getRow(), ROW);
1017
1018
1019 Throwable cause = ClientExceptionsUtil.findException(e.getCause(0));
1020 Assert.assertNotNull(cause);
1021 Assert.assertTrue(cause instanceof RegionMovedException);
1022 }
1023 Assert.assertNotNull("Cached connection is null", conn.getCachedLocation(TABLE_NAME, ROW));
1024 Assert.assertEquals(
1025 "Previous server was " + curServer.getServerName().getHostAndPort(),
1026 destServerName.getPort(),
1027 conn.getCachedLocation(TABLE_NAME, ROW).getRegionLocation().getPort());
1028
1029 Assert.assertFalse(destServer.getRegionsInTransitionInRS()
1030 .containsKey(encodedRegionNameBytes));
1031 Assert.assertFalse(curServer.getRegionsInTransitionInRS()
1032 .containsKey(encodedRegionNameBytes));
1033
1034
1035 LOG.info("Move starting region=" + toMove.getRegionInfo().getRegionNameAsString());
1036 TEST_UTIL.getHBaseAdmin().move(
1037 toMove.getRegionInfo().getEncodedNameAsBytes(),
1038 curServer.getServerName().getServerName().getBytes()
1039 );
1040
1041 while (curServer.getOnlineRegion(regionName) == null ||
1042 destServer.getRegionsInTransitionInRS().containsKey(encodedRegionNameBytes) ||
1043 curServer.getRegionsInTransitionInRS().containsKey(encodedRegionNameBytes) ||
1044 master.getAssignmentManager().getRegionStates().isRegionsInTransition()) {
1045
1046 Thread.sleep(1);
1047 }
1048
1049
1050 Assert.assertNotNull(curServer.getOnlineRegion(regionName));
1051 Assert.assertNull(destServer.getOnlineRegion(regionName));
1052 LOG.info("Move finished for region=" + toMove.getRegionInfo().getRegionNameAsString());
1053
1054
1055 Assert.assertFalse(conn.getCachedLocation(TABLE_NAME, ROW).getRegionLocation().getPort() ==
1056 curServer.getServerName().getPort());
1057
1058 Scan sc = new Scan();
1059 sc.setStopRow(ROW);
1060 sc.setStartRow(ROW);
1061
1062
1063
1064 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1);
1065
1066 try {
1067 ResultScanner rs = table.getScanner(sc);
1068 while (rs.next() != null) {
1069 }
1070 Assert.fail("Unreachable point");
1071 } catch (RetriesExhaustedException e) {
1072 LOG.info("Scan done, expected exception caught: " + e.getClass());
1073 }
1074
1075
1076 Assert.assertNotNull(conn.getCachedLocation(TABLE_NAME, ROW));
1077 Assert.assertEquals(
1078 "Previous server was "+destServer.getServerName().getHostAndPort(),
1079 curServer.getServerName().getPort(),
1080 conn.getCachedLocation(TABLE_NAME, ROW).getRegionLocation().getPort());
1081
1082 TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, RPC_RETRY);
1083 table.close();
1084 }
1085
1086
1087
1088
1089
1090 @Test
1091 public void testConnectionManagement() throws Exception{
1092 Table table0 = TEST_UTIL.createTable(TABLE_NAME1, FAM_NAM);
1093 Connection conn = ConnectionFactory.createConnection(TEST_UTIL.getConfiguration());
1094 HTable table = (HTable) conn.getTable(TABLE_NAME1);
1095 table.close();
1096 assertFalse(conn.isClosed());
1097 assertFalse(table.getPool().isShutdown());
1098 table = (HTable) conn.getTable(TABLE_NAME1);
1099 table.close();
1100 assertFalse(table.getPool().isShutdown());
1101 conn.close();
1102 assertTrue(table.getPool().isShutdown());
1103 table0.close();
1104 }
1105
1106
1107
1108
1109 @Test
1110 public void testCacheSeqNums() throws Exception{
1111 HTable table = TEST_UTIL.createMultiRegionTable(TABLE_NAME2, FAM_NAM);
1112 Put put = new Put(ROW);
1113 put.add(FAM_NAM, ROW, ROW);
1114 table.put(put);
1115 ConnectionManager.HConnectionImplementation conn =
1116 (ConnectionManager.HConnectionImplementation)table.getConnection();
1117
1118 HRegionLocation location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation();
1119 assertNotNull(location);
1120
1121 ServerName anySource = ServerName.valueOf(location.getHostname(), location.getPort() - 1, 0L);
1122
1123
1124 int nextPort = location.getPort() + 1;
1125 conn.updateCachedLocation(location.getRegionInfo(), location.getServerName(),
1126 ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() - 1);
1127 location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation();
1128 Assert.assertEquals(nextPort, location.getPort());
1129
1130
1131 nextPort = location.getPort() + 1;
1132 conn.updateCachedLocation(location.getRegionInfo(), location.getServerName(),
1133 ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() - 1);
1134 location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation();
1135 Assert.assertEquals(nextPort, location.getPort());
1136
1137
1138 nextPort = location.getPort() + 1;
1139 conn.updateCachedLocation(location.getRegionInfo(), anySource,
1140 ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() + 1);
1141 location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation();
1142 Assert.assertEquals(nextPort, location.getPort());
1143
1144
1145 nextPort = location.getPort() + 1;
1146 conn.updateCachedLocation(location.getRegionInfo(), anySource,
1147 ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() - 1);
1148 location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation();
1149 Assert.assertEquals(nextPort - 1, location.getPort());
1150 table.close();
1151 }
1152
1153
1154
1155
1156
1157 @Test
1158 public void testConnectionSameness() throws Exception {
1159 Connection previousConnection = null;
1160 for (int i = 0; i < 2; i++) {
1161
1162 Configuration configuration = TEST_UTIL.getConfiguration();
1163 configuration.set("some_key", String.valueOf(_randy.nextInt()));
1164 LOG.info("The hash code of the current configuration is: "
1165 + configuration.hashCode());
1166 Connection currentConnection = HConnectionManager
1167 .getConnection(configuration);
1168 if (previousConnection != null) {
1169 assertTrue(
1170 "Did not get the same connection even though its key didn't change",
1171 previousConnection == currentConnection);
1172 }
1173 previousConnection = currentConnection;
1174
1175
1176
1177
1178 configuration.set("other_key", String.valueOf(_randy.nextInt()));
1179 }
1180 }
1181
1182
1183
1184
1185
1186
1187
1188 @Deprecated
1189 @Test
1190 public void testConnectionUniqueness() throws Exception {
1191 int zkmaxconnections = TEST_UTIL.getConfiguration().
1192 getInt(HConstants.ZOOKEEPER_MAX_CLIENT_CNXNS,
1193 HConstants.DEFAULT_ZOOKEPER_MAX_CLIENT_CNXNS);
1194
1195
1196
1197 int maxConnections = Math.min(zkmaxconnections - 1, 20);
1198 List<HConnection> connections = new ArrayList<HConnection>(maxConnections);
1199 Connection previousConnection = null;
1200 try {
1201 for (int i = 0; i < maxConnections; i++) {
1202
1203 Configuration configuration = new Configuration(TEST_UTIL.getConfiguration());
1204 configuration.set("some_key", String.valueOf(_randy.nextInt()));
1205 configuration.set(HConstants.HBASE_CLIENT_INSTANCE_ID,
1206 String.valueOf(_randy.nextInt()));
1207 LOG.info("The hash code of the current configuration is: "
1208 + configuration.hashCode());
1209 HConnection currentConnection =
1210 HConnectionManager.getConnection(configuration);
1211 if (previousConnection != null) {
1212 assertTrue("Got the same connection even though its key changed!",
1213 previousConnection != currentConnection);
1214 }
1215
1216
1217
1218
1219 configuration.set("other_key", String.valueOf(_randy.nextInt()));
1220
1221 previousConnection = currentConnection;
1222 LOG.info("The current HConnectionManager#HBASE_INSTANCES cache size is: "
1223 + getHConnectionManagerCacheSize());
1224 Thread.sleep(50);
1225 connections.add(currentConnection);
1226 }
1227 } finally {
1228 for (Connection c: connections) {
1229
1230 HConnectionManager.deleteConnection(c.getConfiguration());
1231 }
1232 }
1233 }
1234
1235 @Test
1236 public void testClosing() throws Exception {
1237 Configuration configuration =
1238 new Configuration(TEST_UTIL.getConfiguration());
1239 configuration.set(HConstants.HBASE_CLIENT_INSTANCE_ID,
1240 String.valueOf(_randy.nextInt()));
1241
1242 Connection c1 = ConnectionFactory.createConnection(configuration);
1243
1244 Connection c2 = ConnectionFactory.createConnection(configuration);
1245
1246 Connection c3 = HConnectionManager.getConnection(configuration);
1247 Connection c4 = HConnectionManager.getConnection(configuration);
1248 assertTrue(c3 == c4);
1249
1250 c1.close();
1251 assertTrue(c1.isClosed());
1252 assertFalse(c2.isClosed());
1253 assertFalse(c3.isClosed());
1254
1255 c3.close();
1256
1257 assertFalse(c3.isClosed());
1258 c3.close();
1259 assertTrue(c3.isClosed());
1260
1261 Connection c5 = HConnectionManager.getConnection(configuration);
1262 assertTrue(c5 != c3);
1263
1264 assertFalse(c2.isClosed());
1265 c2.close();
1266 assertTrue(c2.isClosed());
1267 c5.close();
1268 assertTrue(c5.isClosed());
1269 }
1270
1271
1272
1273
1274
1275 @Test
1276 public void testCreateConnection() throws Exception {
1277 Configuration configuration = TEST_UTIL.getConfiguration();
1278 Connection c1 = ConnectionFactory.createConnection(configuration);
1279 Connection c2 = ConnectionFactory.createConnection(configuration);
1280
1281 assertTrue(c1 != c2);
1282 assertTrue(c1.getConfiguration() == c2.getConfiguration());
1283
1284 Connection c3 = HConnectionManager.getConnection(configuration);
1285 assertTrue(c1 != c3);
1286 assertTrue(c2 != c3);
1287 }
1288
1289
1290
1291
1292
1293
1294
1295 @Test
1296 public void testConnection() throws Exception{
1297
1298 Configuration c = new Configuration();
1299 c.set(HConstants.ZOOKEEPER_QUORUM,
1300 TEST_UTIL.getConfiguration().get(HConstants.ZOOKEEPER_QUORUM));
1301 c.set(HConstants.ZOOKEEPER_CLIENT_PORT ,
1302 TEST_UTIL.getConfiguration().get(HConstants.ZOOKEEPER_CLIENT_PORT));
1303
1304
1305 HConnection conn = HConnectionManager.getConnection(c);
1306 assertTrue( conn.isMasterRunning() );
1307 conn.close();
1308 }
1309
1310 private int setNumTries(HConnectionImplementation hci, int newVal) throws Exception {
1311 Field numTries = hci.getClass().getDeclaredField("numTries");
1312 numTries.setAccessible(true);
1313 Field modifiersField = Field.class.getDeclaredField("modifiers");
1314 modifiersField.setAccessible(true);
1315 modifiersField.setInt(numTries, numTries.getModifiers() & ~Modifier.FINAL);
1316 final int prevNumRetriesVal = (Integer)numTries.get(hci);
1317 numTries.set(hci, newVal);
1318
1319 return prevNumRetriesVal;
1320 }
1321
1322 @Test
1323 public void testMulti() throws Exception {
1324 HTable table = TEST_UTIL.createMultiRegionTable(TABLE_NAME3, FAM_NAM);
1325 try {
1326 ConnectionManager.HConnectionImplementation conn =
1327 ( ConnectionManager.HConnectionImplementation)table.getConnection();
1328
1329
1330
1331 conn.clearRegionCache(TABLE_NAME3);
1332 Assert.assertEquals(0, conn.getNumberOfCachedRegionLocations(TABLE_NAME3));
1333
1334 TEST_UTIL.getHBaseAdmin().setBalancerRunning(false, false);
1335 HMaster master = TEST_UTIL.getMiniHBaseCluster().getMaster();
1336
1337
1338 TEST_UTIL.waitUntilNoRegionsInTransition();
1339
1340 Put put = new Put(ROW_X);
1341 put.add(FAM_NAM, ROW_X, ROW_X);
1342 table.put(put);
1343
1344
1345 HRegionLocation toMove = conn.getCachedLocation(TABLE_NAME3, ROW_X).getRegionLocation();
1346 byte[] regionName = toMove.getRegionInfo().getRegionName();
1347 byte[] encodedRegionNameBytes = toMove.getRegionInfo().getEncodedNameAsBytes();
1348
1349
1350 int curServerId = TEST_UTIL.getHBaseCluster().getServerWith(regionName);
1351 int destServerId = (curServerId == 0 ? 1 : 0);
1352
1353 HRegionServer curServer = TEST_UTIL.getHBaseCluster().getRegionServer(curServerId);
1354 HRegionServer destServer = TEST_UTIL.getHBaseCluster().getRegionServer(destServerId);
1355
1356 ServerName destServerName = destServer.getServerName();
1357
1358
1359 List<Region> regions = curServer.getOnlineRegions(TABLE_NAME3);
1360 byte[] otherRow = null;
1361 for (Region region : regions) {
1362 if (!region.getRegionInfo().getEncodedName().equals(toMove.getRegionInfo().getEncodedName())
1363 && Bytes.BYTES_COMPARATOR.compare(region.getRegionInfo().getStartKey(), ROW_X) < 0) {
1364 otherRow = region.getRegionInfo().getStartKey();
1365 break;
1366 }
1367 }
1368 assertNotNull(otherRow);
1369
1370 if (otherRow.length <= 0) otherRow = Bytes.toBytes("aaa");
1371 Put put2 = new Put(otherRow);
1372 put2.add(FAM_NAM, otherRow, otherRow);
1373 table.put(put2);
1374
1375
1376 Assert.assertTrue(curServer != destServer);
1377 Assert.assertNotEquals(curServer.getServerName(), destServer.getServerName());
1378 Assert.assertNotEquals(toMove.getPort(), destServerName.getPort());
1379 Assert.assertNotNull(curServer.getOnlineRegion(regionName));
1380 Assert.assertNull(destServer.getOnlineRegion(regionName));
1381 Assert.assertFalse(TEST_UTIL.getMiniHBaseCluster().getMaster().
1382 getAssignmentManager().getRegionStates().isRegionsInTransition());
1383
1384
1385
1386 LOG.info("Move starting region="+toMove.getRegionInfo().getRegionNameAsString());
1387 TEST_UTIL.getHBaseAdmin().move(
1388 toMove.getRegionInfo().getEncodedNameAsBytes(),
1389 destServerName.getServerName().getBytes()
1390 );
1391
1392 while (destServer.getOnlineRegion(regionName) == null ||
1393 destServer.getRegionsInTransitionInRS().containsKey(encodedRegionNameBytes) ||
1394 curServer.getRegionsInTransitionInRS().containsKey(encodedRegionNameBytes) ||
1395 master.getAssignmentManager().getRegionStates().isRegionsInTransition()) {
1396
1397 Thread.sleep(1);
1398 }
1399
1400 LOG.info("Move finished for region="+toMove.getRegionInfo().getRegionNameAsString());
1401
1402
1403 Assert.assertNull(curServer.getOnlineRegion(regionName));
1404 Assert.assertNotNull(destServer.getOnlineRegion(regionName));
1405 Assert.assertFalse(destServer.getRegionsInTransitionInRS().containsKey(encodedRegionNameBytes));
1406 Assert.assertFalse(curServer.getRegionsInTransitionInRS().containsKey(encodedRegionNameBytes));
1407
1408
1409
1410 Assert.assertFalse(
1411 conn.getCachedLocation(TABLE_NAME3, ROW_X).getRegionLocation()
1412 .getPort() == destServerName.getPort());
1413
1414
1415 final int prevNumRetriesVal = setNumTries(conn, 2);
1416
1417 Put put3 = new Put(ROW_X);
1418 put3.add(FAM_NAM, ROW_X, ROW_X);
1419 Put put4 = new Put(otherRow);
1420 put4.add(FAM_NAM, otherRow, otherRow);
1421
1422
1423 table.batch(Lists.newArrayList(put4, put3));
1424
1425
1426 setNumTries(conn, prevNumRetriesVal);
1427 } finally {
1428 table.close();
1429 }
1430 }
1431
1432 @Test
1433 public void testErrorBackoffTimeCalculation() throws Exception {
1434
1435 final long ANY_PAUSE = 100;
1436 ServerName location = ServerName.valueOf("127.0.0.1", 1, 0);
1437 ServerName diffLocation = ServerName.valueOf("127.0.0.1", 2, 0);
1438
1439 ManualEnvironmentEdge timeMachine = new ManualEnvironmentEdge();
1440 EnvironmentEdgeManager.injectEdge(timeMachine);
1441 try {
1442 long timeBase = timeMachine.currentTime();
1443 long largeAmountOfTime = ANY_PAUSE * 1000;
1444 ConnectionManager.ServerErrorTracker tracker =
1445 new ConnectionManager.ServerErrorTracker(largeAmountOfTime, 100);
1446
1447
1448 assertEquals(0, tracker.calculateBackoffTime(location, ANY_PAUSE));
1449
1450
1451 tracker.reportServerError(location);
1452 assertEqualsWithJitter(ANY_PAUSE * HConstants.RETRY_BACKOFF[0],
1453 tracker.calculateBackoffTime(location, ANY_PAUSE));
1454 tracker.reportServerError(location);
1455 tracker.reportServerError(location);
1456 tracker.reportServerError(location);
1457 assertEqualsWithJitter(ANY_PAUSE * HConstants.RETRY_BACKOFF[3],
1458 tracker.calculateBackoffTime(location, ANY_PAUSE));
1459
1460
1461 assertEquals(0, tracker.calculateBackoffTime(diffLocation, ANY_PAUSE));
1462 tracker.reportServerError(diffLocation);
1463 assertEqualsWithJitter(ANY_PAUSE * HConstants.RETRY_BACKOFF[0],
1464 tracker.calculateBackoffTime(diffLocation, ANY_PAUSE));
1465
1466
1467 assertEqualsWithJitter(ANY_PAUSE * 2 * HConstants.RETRY_BACKOFF[3],
1468 tracker.calculateBackoffTime(location, ANY_PAUSE * 2));
1469 } finally {
1470 EnvironmentEdgeManager.reset();
1471 }
1472 }
1473
1474 private static void assertEqualsWithJitter(long expected, long actual) {
1475 assertEqualsWithJitter(expected, actual, expected);
1476 }
1477
1478 private static void assertEqualsWithJitter(long expected, long actual, long jitterBase) {
1479 assertTrue("Value not within jitter: " + expected + " vs " + actual,
1480 Math.abs(actual - expected) <= (0.01f * jitterBase));
1481 }
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491 @Ignore ("Flakey test: See HBASE-8996")@Test
1492 public void testDeleteForZKConnLeak() throws Exception {
1493 TEST_UTIL.createTable(TABLE_NAME4, FAM_NAM);
1494 final Configuration config = HBaseConfiguration.create(TEST_UTIL.getConfiguration());
1495 config.setInt("zookeeper.recovery.retry", 1);
1496 config.setInt("zookeeper.recovery.retry.intervalmill", 1000);
1497 config.setInt("hbase.rpc.timeout", 2000);
1498 config.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1);
1499
1500 ThreadPoolExecutor pool = new ThreadPoolExecutor(1, 10,
1501 5, TimeUnit.SECONDS,
1502 new SynchronousQueue<Runnable>(),
1503 Threads.newDaemonThreadFactory("test-hcm-delete"));
1504
1505 pool.submit(new Runnable() {
1506 @Override
1507 public void run() {
1508 while (!Thread.interrupted()) {
1509 try {
1510 HConnection conn = HConnectionManager.getConnection(config);
1511 LOG.info("Connection " + conn);
1512 HConnectionManager.deleteStaleConnection(conn);
1513 LOG.info("Connection closed " + conn);
1514
1515
1516
1517 Threads.sleep(10);
1518 } catch (Exception e) {
1519 }
1520 }
1521 }
1522 });
1523
1524
1525 for (int i = 0; i < 30; i++) {
1526 Connection c1 = null;
1527 try {
1528 c1 = ConnectionManager.getConnectionInternal(config);
1529 LOG.info("HTable connection " + i + " " + c1);
1530 Table table = new HTable(config, TABLE_NAME4, pool);
1531 table.close();
1532 LOG.info("HTable connection " + i + " closed " + c1);
1533 } catch (Exception e) {
1534 LOG.info("We actually want this to happen!!!! So we can see if we are leaking zk", e);
1535 } finally {
1536 if (c1 != null) {
1537 if (c1.isClosed()) {
1538
1539 Field zkwField = c1.getClass().getDeclaredField("keepAliveZookeeper");
1540 zkwField.setAccessible(true);
1541 Object watcher = zkwField.get(c1);
1542
1543 if (watcher != null) {
1544 if (((ZooKeeperWatcher)watcher).getRecoverableZooKeeper().getState().isAlive()) {
1545
1546
1547 Thread.sleep(1000);
1548 if (((ZooKeeperWatcher) watcher).getRecoverableZooKeeper().getState().isAlive()) {
1549 pool.shutdownNow();
1550 fail("Live zookeeper in closed connection");
1551 }
1552 }
1553 }
1554 }
1555 c1.close();
1556 }
1557 }
1558 }
1559 pool.shutdownNow();
1560 }
1561
1562 @Test
1563 public void testConnectionRideOverClusterRestart() throws IOException, InterruptedException {
1564 Configuration config = new Configuration(TEST_UTIL.getConfiguration());
1565
1566 TableName tableName = TableName.valueOf("testConnectionRideOverClusterRestart");
1567 TEST_UTIL.createTable(tableName.getName(), new byte[][] {FAM_NAM}, config).close();
1568
1569 Connection connection = ConnectionFactory.createConnection(config);
1570 Table table = connection.getTable(tableName);
1571
1572
1573 table.get(new Get(Bytes.toBytes("foo")));
1574
1575
1576 TEST_UTIL.shutdownMiniHBaseCluster();
1577 TEST_UTIL.restartHBaseCluster(2);
1578
1579 table.get(new Get(Bytes.toBytes("foo")));
1580 TEST_UTIL.deleteTable(tableName);
1581 table.close();
1582 connection.close();
1583 }
1584 }