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