001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.client;
019
020import static org.junit.jupiter.api.Assertions.assertEquals;
021import static org.junit.jupiter.api.Assertions.assertTrue;
022
023import java.io.IOException;
024import java.util.EnumSet;
025import java.util.stream.Stream;
026import org.apache.hadoop.conf.Configuration;
027import org.apache.hadoop.hbase.ClusterMetrics.Option;
028import org.apache.hadoop.hbase.HBaseParameterizedTestTemplate;
029import org.apache.hadoop.hbase.HBaseTestingUtil;
030import org.apache.hadoop.hbase.HConstants;
031import org.apache.hadoop.hbase.SingleProcessHBaseCluster;
032import org.apache.hadoop.hbase.TableName;
033import org.apache.hadoop.hbase.testclassification.ClientTests;
034import org.apache.hadoop.hbase.testclassification.MediumTests;
035import org.apache.hadoop.hbase.util.Bytes;
036import org.junit.jupiter.api.AfterAll;
037import org.junit.jupiter.api.BeforeAll;
038import org.junit.jupiter.api.Tag;
039import org.junit.jupiter.api.TestTemplate;
040import org.junit.jupiter.params.provider.Arguments;
041
042/**
043 * Test of that unmanaged HConnections are able to reconnect properly (see HBASE-5058)
044 */
045@Tag(MediumTests.TAG)
046@Tag(ClientTests.TAG)
047@HBaseParameterizedTestTemplate(name = "{index}: registryImpl={0}")
048public class TestConnectionReconnect {
049
050  private static final HBaseTestingUtil UTIL = new HBaseTestingUtil();
051
052  private static TableName NAME = TableName.valueOf("reconnect");
053
054  private Class<? extends ConnectionRegistry> registryImpl;
055
056  public TestConnectionReconnect(Class<? extends ConnectionRegistry> registryImpl) {
057    this.registryImpl = registryImpl;
058  }
059
060  @SuppressWarnings("deprecation")
061  public static Stream<Arguments> parameters() {
062    return Stream.of(Arguments.of(RpcConnectionRegistry.class),
063      Arguments.of(ZKConnectionRegistry.class));
064  }
065
066  @BeforeAll
067  public static void setUpBeforeAll() throws Exception {
068    UTIL.startMiniCluster(1);
069    UTIL.createTable(NAME, HConstants.CATALOG_FAMILY);
070    UTIL.waitTableAvailable(NAME);
071  }
072
073  @AfterAll
074  public static void tearDownAfterAll() throws Exception {
075    UTIL.shutdownMiniCluster();
076  }
077
078  private Connection getConnection() throws IOException {
079    Configuration conf = new Configuration(UTIL.getConfiguration());
080    conf.setClass(HConstants.CLIENT_CONNECTION_REGISTRY_IMPL_CONF_KEY, registryImpl,
081      ConnectionRegistry.class);
082    conf.set(RpcConnectionRegistry.BOOTSTRAP_NODES,
083      UTIL.getMiniHBaseCluster().getRegionServer(0).getServerName().getAddress().toString());
084    return ConnectionFactory.createConnection(conf);
085  }
086
087  @TestTemplate
088  public void testReconnect() throws Exception {
089    try (Connection conn = getConnection()) {
090      try (Table t = conn.getTable(NAME); Admin admin = conn.getAdmin()) {
091        assertTrue(admin.tableExists(NAME));
092        assertTrue(t.get(new Get(Bytes.toBytes(0))).isEmpty());
093      }
094
095      // stop the master
096      SingleProcessHBaseCluster cluster = UTIL.getHBaseCluster();
097
098      cluster.stopMaster(0, false);
099      cluster.waitOnMaster(0);
100
101      // start up a new master
102      cluster.startMaster();
103      assertTrue(cluster.waitForActiveAndReadyMaster());
104
105      // test that the same unmanaged connection works with a new
106      // Admin and can connect to the new master;
107      try (Admin admin = conn.getAdmin()) {
108        assertTrue(admin.tableExists(NAME));
109        assertEquals(
110          admin.getClusterMetrics(EnumSet.of(Option.LIVE_SERVERS)).getLiveServerMetrics().size(),
111          1);
112      }
113    }
114  }
115}