@Test (timeout=120000) public void abortingHConnectionRemovesItselfFromHCM() throws Exception { // Save off current HConnections Map<HConnectionKey, HConnectionImplementation> oldHBaseInstances = new HashMap<HConnectionKey, HConnectionImplementation>(); oldHBaseInstances.putAll(ConnectionManager.CONNECTION_INSTANCES); ConnectionManager.CONNECTION_INSTANCES.clear(); try { HConnection connection = HConnectionManager.getConnection(TEST_UTIL.getConfiguration()); connection.abort("test abortingHConnectionRemovesItselfFromHCM", new Exception( "test abortingHConnectionRemovesItselfFromHCM")); Assert.assertNotSame(connection, HConnectionManager.getConnection(TEST_UTIL.getConfiguration())); } finally { // Put original HConnections back ConnectionManager.CONNECTION_INSTANCES.clear(); ConnectionManager.CONNECTION_INSTANCES.putAll(oldHBaseInstances); } }
@Test public void testMetaLookupThreadPoolCreated() throws Exception { byte[] TABLE = Bytes.toBytes("testMetaLookupThreadPoolCreated"); byte[][] FAMILIES = new byte[][] { Bytes.toBytes("foo") }; if (TEST_UTIL.getHBaseAdmin().tableExists(TABLE)) { TEST_UTIL.getHBaseAdmin().disableTable(TABLE); TEST_UTIL.getHBaseAdmin().deleteTable(TABLE); } try (Table htable = TEST_UTIL.createTable(TABLE, FAMILIES, TEST_UTIL.getConfiguration());) { byte[] row = "test".getBytes(); HConnectionImplementation c = ((HConnectionImplementation)((HTable)htable).connection); // check that metalookup pool would get created c.relocateRegion(TABLE, row); ExecutorService ex = c.getCurrentMetaLookupPool(); assert(ex != null); } }
/** * Get a Mocked {@link HConnection} that goes with the passed <code>conf</code> * configuration instance. Minimally the mock will return * <code>conf</conf> when {@link ClusterConnection#getConfiguration()} is invoked. * Be sure to shutdown the connection when done by calling * {@link HConnectionManager#deleteConnection(Configuration)} else it * will stick around; this is probably not what you want. * @param conf configuration * @return HConnection object for <code>conf</code> * @throws ZooKeeperConnectionException */ public static ClusterConnection getMockedConnection(final Configuration conf) throws ZooKeeperConnectionException { HConnectionKey connectionKey = new HConnectionKey(conf); synchronized (ConnectionManager.CONNECTION_INSTANCES) { HConnectionImplementation connection = ConnectionManager.CONNECTION_INSTANCES.get(connectionKey); if (connection == null) { connection = Mockito.mock(HConnectionImplementation.class); Mockito.when(connection.getConfiguration()).thenReturn(conf); Mockito.when(connection.getRpcControllerFactory()).thenReturn( Mockito.mock(RpcControllerFactory.class)); // we need a real retrying caller RpcRetryingCallerFactory callerFactory = new RpcRetryingCallerFactory(conf); Mockito.when(connection.getRpcRetryingCallerFactory()).thenReturn(callerFactory); ConnectionManager.CONNECTION_INSTANCES.put(connectionKey, connection); } return connection; } }
@Test public void abortingHConnectionRemovesItselfFromHCM() throws Exception { // Save off current HConnections Map<HConnectionKey, HConnectionImplementation> oldHBaseInstances = new HashMap<HConnectionKey, HConnectionImplementation>(); oldHBaseInstances.putAll(ConnectionManager.CONNECTION_INSTANCES); ConnectionManager.CONNECTION_INSTANCES.clear(); try { HConnection connection = HConnectionManager.getConnection(TEST_UTIL.getConfiguration()); connection.abort("test abortingHConnectionRemovesItselfFromHCM", new Exception( "test abortingHConnectionRemovesItselfFromHCM")); Assert.assertNotSame(connection, HConnectionManager.getConnection(TEST_UTIL.getConfiguration())); } finally { // Put original HConnections back ConnectionManager.CONNECTION_INSTANCES.clear(); ConnectionManager.CONNECTION_INSTANCES.putAll(oldHBaseInstances); } }
private int setNumTries(HConnectionImplementation hci, int newVal) throws Exception { Field numTries = hci.getClass().getDeclaredField("numTries"); numTries.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(numTries, numTries.getModifiers() & ~Modifier.FINAL); final int prevNumRetriesVal = (Integer)numTries.get(hci); numTries.set(hci, newVal); return prevNumRetriesVal; }
/** * @param connection */ private static void mockRegionLocator(final HConnectionImplementation connection) { try { Mockito.when(connection.getRegionLocator(Mockito.any(TableName.class))).thenAnswer( new Answer<RegionLocator>() { @Override public RegionLocator answer(InvocationOnMock invocation) throws Throwable { TableName tableName = (TableName) invocation.getArguments()[0]; return new HRegionLocator(tableName, connection); } }); } catch (IOException e) { } }
/** * Get a Mockito spied-upon {@link ClusterConnection} that goes with the passed * <code>conf</code> configuration instance. * Be sure to shutdown the connection when done by calling * {@link HConnectionManager#deleteConnection(Configuration)} else it * will stick around; this is probably not what you want. * @param conf configuration * @return HConnection object for <code>conf</code> * @throws ZooKeeperConnectionException * @see @link * {http://mockito.googlecode.com/svn/branches/1.6/javadoc/org/mockito/Mockito.html#spy(T)} */ public static ClusterConnection getSpiedConnection(final Configuration conf) throws IOException { HConnectionKey connectionKey = new HConnectionKey(conf); synchronized (ConnectionManager.CONNECTION_INSTANCES) { HConnectionImplementation connection = ConnectionManager.CONNECTION_INSTANCES.get(connectionKey); if (connection == null) { connection = Mockito.spy(new HConnectionImplementation(conf, true)); ConnectionManager.CONNECTION_INSTANCES.put(connectionKey, connection); } return connection; } }
public static ClusterConnection getSpiedClusterConnection(final Configuration conf) throws IOException { HConnectionKey connectionKey = new HConnectionKey(conf); synchronized (ConnectionManager.CONNECTION_INSTANCES) { HConnectionImplementation connection = ConnectionManager.CONNECTION_INSTANCES.get(connectionKey); if (connection == null) { connection = Mockito.spy(new HConnectionImplementation(conf, true)); ConnectionManager.CONNECTION_INSTANCES.put(connectionKey, connection); } return connection; } }
/** * Get a Mocked {@link HConnection} that goes with the passed <code>conf</code> * configuration instance. Minimally the mock will return * <code>conf</conf> when {@link ClusterConnection#getConfiguration()} is invoked. * Be sure to shutdown the connection when done by calling * {@link HConnectionManager#deleteConnection(Configuration)} else it * will stick around; this is probably not what you want. * @param conf configuration * @return HConnection object for <code>conf</code> * @throws ZooKeeperConnectionException */ public static ClusterConnection getMockedConnection(final Configuration conf) throws ZooKeeperConnectionException { HConnectionKey connectionKey = new HConnectionKey(conf); synchronized (ConnectionManager.CONNECTION_INSTANCES) { HConnectionImplementation connection = ConnectionManager.CONNECTION_INSTANCES.get(connectionKey); if (connection == null) { connection = Mockito.mock(HConnectionImplementation.class); Mockito.when(connection.getConfiguration()).thenReturn(conf); ConnectionManager.CONNECTION_INSTANCES.put(connectionKey, connection); } return connection; } }
/** * Get a Mocked {@link HConnection} that goes with the passed <code>conf</code> * configuration instance. Minimally the mock will return * <code>conf</conf> when {@link HConnection#getConfiguration()} is invoked. * Be sure to shutdown the connection when done by calling * {@link HConnectionManager#deleteConnection(Configuration)} else it * will stick around; this is probably not what you want. * @param conf configuration * @return HConnection object for <code>conf</code> * @throws ZooKeeperConnectionException */ public static ClusterConnection getMockedConnection(final Configuration conf) throws ZooKeeperConnectionException { HConnectionKey connectionKey = new HConnectionKey(conf); synchronized (ConnectionManager.CONNECTION_INSTANCES) { HConnectionImplementation connection = ConnectionManager.CONNECTION_INSTANCES.get(connectionKey); if (connection == null) { connection = Mockito.mock(HConnectionImplementation.class); Mockito.when(connection.getConfiguration()).thenReturn(conf); ConnectionManager.CONNECTION_INSTANCES.put(connectionKey, connection); } return connection; } }
/** * Calls {@link #getMockedConnection(Configuration)} and then mocks a few * more of the popular {@link HConnection} methods so they do 'normal' * operation (see return doc below for list). Be sure to shutdown the * connection when done by calling * {@link HConnectionManager#deleteConnection(Configuration)} else it * will stick around; this is probably not what you want. * * @param conf Configuration to use * @param admin An AdminProtocol; can be null but is usually * itself a mock. * @param client A ClientProtocol; can be null but is usually * itself a mock. * @param sn ServerName to include in the region location returned by this * <code>connection</code> * @param hri HRegionInfo to include in the location returned when * getRegionLocation is called on the mocked connection * @return Mock up a connection that returns a {@link Configuration} when * {@link HConnection#getConfiguration()} is called, a 'location' when * {@link HConnection#getRegionLocation(org.apache.hadoop.hbase.TableName, byte[], boolean)} is called, * and that returns the passed {@link AdminProtos.AdminService.BlockingInterface} instance when * {@link HConnection#getAdmin(ServerName)} is called, returns the passed * {@link ClientProtos.ClientService.BlockingInterface} instance when * {@link HConnection#getClient(ServerName)} is called (Be sure to call * {@link HConnectionManager#deleteConnection(Configuration)} * when done with this mocked Connection. * @throws IOException */ public static ClusterConnection getMockedConnectionAndDecorate(final Configuration conf, final AdminProtos.AdminService.BlockingInterface admin, final ClientProtos.ClientService.BlockingInterface client, final ServerName sn, final HRegionInfo hri) throws IOException { HConnectionImplementation c = Mockito.mock(HConnectionImplementation.class); Mockito.when(c.getConfiguration()).thenReturn(conf); ConnectionManager.CONNECTION_INSTANCES.put(new HConnectionKey(conf), c); Mockito.doNothing().when(c).close(); // Make it so we return a particular location when asked. final HRegionLocation loc = new HRegionLocation(hri, sn); Mockito.when(c.getRegionLocation((TableName) Mockito.any(), (byte[]) Mockito.any(), Mockito.anyBoolean())). thenReturn(loc); Mockito.when(c.locateRegion((TableName) Mockito.any(), (byte[]) Mockito.any())). thenReturn(loc); if (admin != null) { // If a call to getAdmin, return this implementation. Mockito.when(c.getAdmin(Mockito.any(ServerName.class))). thenReturn(admin); } if (client != null) { // If a call to getClient, return this client. Mockito.when(c.getClient(Mockito.any(ServerName.class))). thenReturn(client); } NonceGenerator ng = Mockito.mock(NonceGenerator.class); Mockito.when(c.getNonceGenerator()).thenReturn(ng); Mockito.when(c.getAsyncProcess()).thenReturn( new AsyncProcess(c, conf, null, RpcRetryingCallerFactory.instantiate(conf), false, RpcControllerFactory.instantiate(conf))); Mockito.doNothing().when(c).incCount(); Mockito.doNothing().when(c).decCount(); return c; }
/** * Get a Mockito spied-upon {@link HConnection} that goes with the passed * <code>conf</code> configuration instance. * Be sure to shutdown the connection when done by calling * {@link HConnectionManager#deleteConnection(Configuration)} else it * will stick around; this is probably not what you want. * @param conf configuration * @return HConnection object for <code>conf</code> * @throws ZooKeeperConnectionException * @see @link * {http://mockito.googlecode.com/svn/branches/1.6/javadoc/org/mockito/Mockito.html#spy(T)} */ public static HConnection getSpiedConnection(final Configuration conf) throws IOException { HConnectionKey connectionKey = new HConnectionKey(conf); synchronized (ConnectionManager.CONNECTION_INSTANCES) { HConnectionImplementation connection = ConnectionManager.CONNECTION_INSTANCES.get(connectionKey); if (connection == null) { connection = Mockito.spy(new HConnectionImplementation(conf, true)); ConnectionManager.CONNECTION_INSTANCES.put(connectionKey, connection); } return connection; } }
@Test public void testClusterConnection() throws IOException { ThreadPoolExecutor otherPool = new ThreadPoolExecutor(1, 1, 5, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), Threads.newDaemonThreadFactory("test-hcm")); HConnection con1 = HConnectionManager.createConnection(TEST_UTIL.getConfiguration()); HConnection con2 = HConnectionManager.createConnection(TEST_UTIL.getConfiguration(), otherPool); // make sure the internally created ExecutorService is the one passed assertTrue(otherPool == ((HConnectionImplementation)con2).getCurrentBatchPool()); String tableName = "testClusterConnection"; TEST_UTIL.createTable(tableName.getBytes(), FAM_NAM).close(); HTable t = (HTable)con1.getTable(tableName, otherPool); // make sure passing a pool to the getTable does not trigger creation of an internal pool assertNull("Internal Thread pool should be null", ((HConnectionImplementation)con1).getCurrentBatchPool()); // table should use the pool passed assertTrue(otherPool == t.getPool()); t.close(); t = (HTable)con2.getTable(tableName); // table should use the connectin's internal pool assertTrue(otherPool == t.getPool()); t.close(); t = (HTable)con2.getTable(Bytes.toBytes(tableName)); // try other API too assertTrue(otherPool == t.getPool()); t.close(); t = (HTable)con2.getTable(TableName.valueOf(tableName)); // try other API too assertTrue(otherPool == t.getPool()); t.close(); t = (HTable)con1.getTable(tableName); ExecutorService pool = ((HConnectionImplementation)con1).getCurrentBatchPool(); // make sure an internal pool was created assertNotNull("An internal Thread pool should have been created", pool); // and that the table is using it assertTrue(t.getPool() == pool); t.close(); t = (HTable)con1.getTable(tableName); // still using the *same* internal pool assertTrue(t.getPool() == pool); t.close(); con1.close(); // if the pool was created on demand it should be closed upon connection close assertTrue(pool.isShutdown()); con2.close(); // if the pool is passed, it is not closed assertFalse(otherPool.isShutdown()); otherPool.shutdownNow(); }
@Ignore @Test (expected = RegionServerStoppedException.class) public void testClusterStatus() throws Exception { TableName tn = TableName.valueOf("testClusterStatus"); byte[] cf = "cf".getBytes(); byte[] rk = "rk1".getBytes(); JVMClusterUtil.RegionServerThread rs = TEST_UTIL.getHBaseCluster().startRegionServer(); rs.waitForServerOnline(); final ServerName sn = rs.getRegionServer().getServerName(); HTable t = TEST_UTIL.createTable(tn, cf); TEST_UTIL.waitTableAvailable(tn); while(TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager(). getRegionStates().isRegionsInTransition()){ Thread.sleep(1); } final HConnectionImplementation hci = (HConnectionImplementation)t.getConnection(); while (t.getRegionLocation(rk).getPort() != sn.getPort()){ TEST_UTIL.getHBaseAdmin().move(t.getRegionLocation(rk).getRegionInfo(). getEncodedNameAsBytes(), Bytes.toBytes(sn.toString())); while(TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager(). getRegionStates().isRegionsInTransition()){ Thread.sleep(1); } hci.clearRegionCache(tn); } Assert.assertNotNull(hci.clusterStatusListener); TEST_UTIL.assertRegionOnServer(t.getRegionLocation(rk).getRegionInfo(), sn, 20000); Put p1 = new Put(rk); p1.add(cf, "qual".getBytes(), "val".getBytes()); t.put(p1); rs.getRegionServer().abort("I'm dead"); // We want the status to be updated. That's a least 10 second TEST_UTIL.waitFor(40000, 1000, true, new Waiter.Predicate<Exception>() { @Override public boolean evaluate() throws Exception { return TEST_UTIL.getHBaseCluster().getMaster().getServerManager(). getDeadServers().isDeadServer(sn); } }); TEST_UTIL.waitFor(40000, 1000, true, new Waiter.Predicate<Exception>() { @Override public boolean evaluate() throws Exception { return hci.clusterStatusListener.isDeadServer(sn); } }); t.close(); hci.getClient(sn); // will throw an exception: RegionServerStoppedException }
/** * Test that the connection to the dead server is cut immediately when we receive the * notification. * @throws Exception */ @Test public void testConnectionCut() throws Exception { TableName tableName = TableName.valueOf("HCM-testConnectionCut"); TEST_UTIL.createTable(tableName, FAM_NAM).close(); boolean previousBalance = TEST_UTIL.getHBaseAdmin().setBalancerRunning(false, true); Configuration c2 = new Configuration(TEST_UTIL.getConfiguration()); // We want to work on a separate connection. c2.set(HConstants.HBASE_CLIENT_INSTANCE_ID, String.valueOf(-1)); c2.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1); c2.setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 30 * 1000); HTable table = new HTable(c2, tableName); Put p = new Put(FAM_NAM); p.add(FAM_NAM, FAM_NAM, FAM_NAM); table.put(p); final HConnectionImplementation hci = (HConnectionImplementation)table.getConnection(); final HRegionLocation loc = table.getRegionLocation(FAM_NAM); Get get = new Get(FAM_NAM); Assert.assertNotNull(table.get(get)); get = new Get(FAM_NAM); get.setFilter(new BlockingFilter()); // This thread will mark the server as dead while we're waiting during a get. Thread t = new Thread() { @Override public void run() { synchronized (syncBlockingFilter) { try { syncBlockingFilter.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } hci.clusterStatusListener.deadServerHandler.newDead(loc.getServerName()); } }; t.start(); try { table.get(get); Assert.fail(); } catch (IOException expected) { LOG.debug("Received: " + expected); Assert.assertFalse(expected instanceof SocketTimeoutException); Assert.assertFalse(syncBlockingFilter.get()); } finally { syncBlockingFilter.set(true); t.join(); HConnectionManager.getConnection(c2).close(); TEST_UTIL.getHBaseAdmin().setBalancerRunning(previousBalance, true); } table.close(); }
/** * Test that stale cache updates don't override newer cached values. */ @Test public void testCacheSeqNums() throws Exception{ HTable table = TEST_UTIL.createMultiRegionTable(TABLE_NAME2, FAM_NAM); Put put = new Put(ROW); put.add(FAM_NAM, ROW, ROW); table.put(put); ConnectionManager.HConnectionImplementation conn = (ConnectionManager.HConnectionImplementation)table.getConnection(); HRegionLocation location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation(); assertNotNull(location); ServerName anySource = ServerName.valueOf(location.getHostname(), location.getPort() - 1, 0L); // Same server as already in cache reporting - overwrites any value despite seqNum. int nextPort = location.getPort() + 1; conn.updateCachedLocation(location.getRegionInfo(), location.getServerName(), ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() - 1); location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation(); Assert.assertEquals(nextPort, location.getPort()); // No source specified - same. nextPort = location.getPort() + 1; conn.updateCachedLocation(location.getRegionInfo(), location.getServerName(), ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() - 1); location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation(); Assert.assertEquals(nextPort, location.getPort()); // Higher seqNum - overwrites lower seqNum. nextPort = location.getPort() + 1; conn.updateCachedLocation(location.getRegionInfo(), anySource, ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() + 1); location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation(); Assert.assertEquals(nextPort, location.getPort()); // Lower seqNum - does not overwrite higher seqNum. nextPort = location.getPort() + 1; conn.updateCachedLocation(location.getRegionInfo(), anySource, ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() - 1); location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation(); Assert.assertEquals(nextPort - 1, location.getPort()); table.close(); }
/** * Calls {@link #getMockedConnection(Configuration)} and then mocks a few * more of the popular {@link ClusterConnection} methods so they do 'normal' * operation (see return doc below for list). Be sure to shutdown the * connection when done by calling * {@link HConnectionManager#deleteConnection(Configuration)} else it * will stick around; this is probably not what you want. * * @param conf Configuration to use * @param admin An AdminProtocol; can be null but is usually * itself a mock. * @param client A ClientProtocol; can be null but is usually * itself a mock. * @param sn ServerName to include in the region location returned by this * <code>connection</code> * @param hri HRegionInfo to include in the location returned when * getRegionLocator is called on the mocked connection * @return Mock up a connection that returns a {@link Configuration} when * {@link ClusterConnection#getConfiguration()} is called, a 'location' when * {@link ClusterConnection#getRegionLocation(org.apache.hadoop.hbase.TableName, byte[], boolean)} * is called, * and that returns the passed {@link AdminProtos.AdminService.BlockingInterface} instance when * {@link ClusterConnection#getAdmin(ServerName)} is called, returns the passed * {@link ClientProtos.ClientService.BlockingInterface} instance when * {@link ClusterConnection#getClient(ServerName)} is called (Be sure to call * {@link HConnectionManager#deleteConnection(Configuration)} * when done with this mocked Connection. * @throws IOException */ public static ClusterConnection getMockedConnectionAndDecorate(final Configuration conf, final AdminProtos.AdminService.BlockingInterface admin, final ClientProtos.ClientService.BlockingInterface client, final ServerName sn, final HRegionInfo hri) throws IOException { HConnectionImplementation c = Mockito.mock(HConnectionImplementation.class); Mockito.when(c.getConfiguration()).thenReturn(conf); ConnectionManager.CONNECTION_INSTANCES.put(new HConnectionKey(conf), c); Mockito.doNothing().when(c).close(); // Make it so we return a particular location when asked. final HRegionLocation loc = new HRegionLocation(hri, sn); mockRegionLocator(c); Mockito.when(c.getRegionLocation((TableName) Mockito.any(), (byte[]) Mockito.any(), Mockito.anyBoolean())). thenReturn(loc); Mockito.when(c.locateRegion((TableName) Mockito.any(), (byte[]) Mockito.any())). thenReturn(loc); Mockito.when(c.locateRegion((TableName) Mockito.any(), (byte[]) Mockito.any(), Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.anyInt())) .thenReturn(new RegionLocations(loc)); if (admin != null) { // If a call to getAdmin, return this implementation. Mockito.when(c.getAdmin(Mockito.any(ServerName.class))). thenReturn(admin); } if (client != null) { // If a call to getClient, return this client. Mockito.when(c.getClient(Mockito.any(ServerName.class))). thenReturn(client); } NonceGenerator ng = Mockito.mock(NonceGenerator.class); Mockito.when(c.getNonceGenerator()).thenReturn(ng); Mockito.when(c.getAsyncProcess()).thenReturn( new AsyncProcess(c, conf, null, RpcRetryingCallerFactory.instantiate(conf), false, RpcControllerFactory.instantiate(conf))); Mockito.doNothing().when(c).incCount(); Mockito.doNothing().when(c).decCount(); Mockito.when(c.getNewRpcRetryingCallerFactory(conf)).thenReturn( RpcRetryingCallerFactory.instantiate(conf, RetryingCallerInterceptorFactory.NO_OP_INTERCEPTOR, null)); Mockito.when(c.getRpcControllerFactory()).thenReturn(Mockito.mock(RpcControllerFactory.class)); HTableInterface t = Mockito.mock(HTableInterface.class); Mockito.when(c.getTable((TableName)Mockito.any())).thenReturn(t); ResultScanner rs = Mockito.mock(ResultScanner.class); Mockito.when(t.getScanner((Scan)Mockito.any())).thenReturn(rs); return c; }
@BeforeClass public static void beforeClass() { HConnectionImplementation mocked = Mockito.mock(HConnectionImplementation.class); Mockito.when(mocked.toString()).thenReturn("mocked-connection"); METRICS = new MetricsConnection(Mockito.mock(HConnectionImplementation.class)); }
@Ignore @Test(expected = RegionServerStoppedException.class) public void testClusterStatus() throws Exception { if (!isJavaOk){ // This test requires jdk 1.7+ throw new RegionServerStoppedException("as expected by the test..."); } TableName tn = TableName.valueOf("testClusterStatus"); byte[] cf = "cf".getBytes(); byte[] rk = "rk1".getBytes(); JVMClusterUtil.RegionServerThread rs = TEST_UTIL.getHBaseCluster().startRegionServer(); rs.waitForServerOnline(); final ServerName sn = rs.getRegionServer().getServerName(); HTable t = TEST_UTIL.createTable(tn, cf); TEST_UTIL.waitTableAvailable(tn); while(TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager(). getRegionStates().isRegionsInTransition()){ Thread.sleep(1); } final HConnectionImplementation hci = (HConnectionImplementation)t.getConnection(); while (t.getRegionLocation(rk).getPort() != sn.getPort()){ TEST_UTIL.getHBaseAdmin().move(t.getRegionLocation(rk).getRegionInfo(). getEncodedNameAsBytes(), Bytes.toBytes(sn.toString())); while(TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager(). getRegionStates().isRegionsInTransition()){ Thread.sleep(1); } hci.clearRegionCache(tn); } Assert.assertNotNull(hci.clusterStatusListener); TEST_UTIL.assertRegionOnServer(t.getRegionLocation(rk).getRegionInfo(), sn, 20000); Put p1 = new Put(rk); p1.add(cf, "qual".getBytes(), "val".getBytes()); t.put(p1); rs.getRegionServer().abort("I'm dead"); // We want the status to be updated. That's a least 10 second TEST_UTIL.waitFor(40000, 1000, true, new Waiter.Predicate<Exception>() { @Override public boolean evaluate() throws Exception { return TEST_UTIL.getHBaseCluster().getMaster().getServerManager(). getDeadServers().isDeadServer(sn); } }); TEST_UTIL.waitFor(40000, 1000, true, new Waiter.Predicate<Exception>() { @Override public boolean evaluate() throws Exception { return hci.clusterStatusListener.isDeadServer(sn); } }); t.close(); hci.getClient(sn); // will throw an exception: RegionServerStoppedException }
/** * Test that the connection to the dead server is cut immediately when we receive the * notification. * @throws Exception */ @Test public void testConnectionCut() throws Exception { if (!isJavaOk){ // This test requires jdk 1.7+ return; } TableName tableName = TableName.valueOf("HCM-testConnectionCut"); TEST_UTIL.createTable(tableName, FAM_NAM).close(); boolean previousBalance = TEST_UTIL.getHBaseAdmin().setBalancerRunning(false, true); Configuration c2 = new Configuration(TEST_UTIL.getConfiguration()); // We want to work on a separate connection. c2.set(HConstants.HBASE_CLIENT_INSTANCE_ID, String.valueOf(-1)); c2.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1); c2.setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 30 * 1000); HTable table = new HTable(c2, tableName); Put p = new Put(FAM_NAM); p.add(FAM_NAM, FAM_NAM, FAM_NAM); table.put(p); final HConnectionImplementation hci = (HConnectionImplementation)table.getConnection(); final HRegionLocation loc = table.getRegionLocation(FAM_NAM); Get get = new Get(FAM_NAM); Assert.assertNotNull(table.get(get)); get = new Get(FAM_NAM); get.setFilter(new BlockingFilter()); // This thread will mark the server as dead while we're waiting during a get. Thread t = new Thread() { @Override public void run() { synchronized (syncBlockingFilter) { try { syncBlockingFilter.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } hci.clusterStatusListener.deadServerHandler.newDead(loc.getServerName()); } }; t.start(); try { table.get(get); Assert.fail(); } catch (IOException expected) { LOG.debug("Received: " + expected); Assert.assertFalse(expected instanceof SocketTimeoutException); Assert.assertFalse(syncBlockingFilter.get()); } finally { syncBlockingFilter.set(true); t.join(); HConnectionManager.getConnection(c2).close(); TEST_UTIL.getHBaseAdmin().setBalancerRunning(previousBalance, true); } table.close(); }
/** * Test that stale cache updates don't override newer cached values. */ @Test(timeout = 60000) public void testCacheSeqNums() throws Exception{ HTable table = TEST_UTIL.createTable(TABLE_NAME2, FAM_NAM); TEST_UTIL.createMultiRegions(table, FAM_NAM); Put put = new Put(ROW); put.add(FAM_NAM, ROW, ROW); table.put(put); ConnectionManager.HConnectionImplementation conn = (ConnectionManager.HConnectionImplementation)table.getConnection(); HRegionLocation location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation(); assertNotNull(location); ServerName anySource = ServerName.valueOf(location.getHostname(), location.getPort() - 1, 0L); // Same server as already in cache reporting - overwrites any value despite seqNum. int nextPort = location.getPort() + 1; conn.updateCachedLocation(location.getRegionInfo(), location.getServerName(), ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() - 1); location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation(); Assert.assertEquals(nextPort, location.getPort()); // No source specified - same. nextPort = location.getPort() + 1; conn.updateCachedLocation(location.getRegionInfo(), location.getServerName(), ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() - 1); location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation(); Assert.assertEquals(nextPort, location.getPort()); // Higher seqNum - overwrites lower seqNum. nextPort = location.getPort() + 1; conn.updateCachedLocation(location.getRegionInfo(), anySource, ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() + 1); location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation(); Assert.assertEquals(nextPort, location.getPort()); // Lower seqNum - does not overwrite higher seqNum. nextPort = location.getPort() + 1; conn.updateCachedLocation(location.getRegionInfo(), anySource, ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() - 1); location = conn.getCachedLocation(TABLE_NAME2, ROW).getRegionLocation(); Assert.assertEquals(nextPort - 1, location.getPort()); table.close(); }
/** * Calls {@link #getMockedConnection(Configuration)} and then mocks a few * more of the popular {@link ClusterConnection} methods so they do 'normal' * operation (see return doc below for list). Be sure to shutdown the * connection when done by calling * {@link HConnectionManager#deleteConnection(Configuration)} else it * will stick around; this is probably not what you want. * * @param conf Configuration to use * @param admin An AdminProtocol; can be null but is usually * itself a mock. * @param client A ClientProtocol; can be null but is usually * itself a mock. * @param sn ServerName to include in the region location returned by this * <code>connection</code> * @param hri HRegionInfo to include in the location returned when * getRegionLocator is called on the mocked connection * @return Mock up a connection that returns a {@link Configuration} when * {@link ClusterConnection#getConfiguration()} is called, a 'location' when * {@link ClusterConnection#getRegionLocation(org.apache.hadoop.hbase.TableName, byte[], boolean)} * is called, * and that returns the passed {@link AdminProtos.AdminService.BlockingInterface} instance when * {@link ClusterConnection#getAdmin(ServerName)} is called, returns the passed * {@link ClientProtos.ClientService.BlockingInterface} instance when * {@link ClusterConnection#getClient(ServerName)} is called (Be sure to call * {@link HConnectionManager#deleteConnection(Configuration)} * when done with this mocked Connection. * @throws IOException */ public static ClusterConnection getMockedConnectionAndDecorate(final Configuration conf, final AdminProtos.AdminService.BlockingInterface admin, final ClientProtos.ClientService.BlockingInterface client, final ServerName sn, final HRegionInfo hri) throws IOException { HConnectionImplementation c = Mockito.mock(HConnectionImplementation.class); Mockito.when(c.getConfiguration()).thenReturn(conf); ConnectionManager.CONNECTION_INSTANCES.put(new HConnectionKey(conf), c); Mockito.doNothing().when(c).close(); // Make it so we return a particular location when asked. final HRegionLocation loc = new HRegionLocation(hri, sn); Mockito.when(c.getRegionLocation((TableName) Mockito.any(), (byte[]) Mockito.any(), Mockito.anyBoolean())). thenReturn(loc); Mockito.when(c.locateRegion((TableName) Mockito.any(), (byte[]) Mockito.any())). thenReturn(loc); Mockito.when(c.locateRegion((TableName) Mockito.any(), (byte[]) Mockito.any(), Mockito.anyBoolean(), Mockito.anyBoolean(), Mockito.anyInt())) .thenReturn(new RegionLocations(loc)); if (admin != null) { // If a call to getAdmin, return this implementation. Mockito.when(c.getAdmin(Mockito.any(ServerName.class))). thenReturn(admin); } if (client != null) { // If a call to getClient, return this client. Mockito.when(c.getClient(Mockito.any(ServerName.class))). thenReturn(client); } NonceGenerator ng = Mockito.mock(NonceGenerator.class); Mockito.when(c.getNonceGenerator()).thenReturn(ng); Mockito.when(c.getAsyncProcess()).thenReturn( new AsyncProcess(c, conf, null, RpcRetryingCallerFactory.instantiate(conf), false, RpcControllerFactory.instantiate(conf))); Mockito.doNothing().when(c).incCount(); Mockito.doNothing().when(c).decCount(); Mockito.when(c.getNewRpcRetryingCallerFactory(conf)).thenReturn( RpcRetryingCallerFactory.instantiate(conf, RetryingCallerInterceptorFactory.NO_OP_INTERCEPTOR, null)); HTableInterface t = Mockito.mock(HTableInterface.class); Mockito.when(c.getTable((TableName)Mockito.any())).thenReturn(t); ResultScanner rs = Mockito.mock(ResultScanner.class); Mockito.when(t.getScanner((Scan)Mockito.any())).thenReturn(rs); return c; }
@Test(expected = RegionServerStoppedException.class) public void testClusterStatus() throws Exception { TableName tn = TableName.valueOf("testClusterStatus"); byte[] cf = "cf".getBytes(); byte[] rk = "rk1".getBytes(); JVMClusterUtil.RegionServerThread rs = TEST_UTIL.getHBaseCluster().startRegionServer(); rs.waitForServerOnline(); final ServerName sn = rs.getRegionServer().getServerName(); HTable t = TEST_UTIL.createTable(tn, cf); TEST_UTIL.waitTableAvailable(tn.getName()); while(TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager(). getRegionStates().isRegionsInTransition()){ Thread.sleep(1); } final HConnectionImplementation hci = (HConnectionImplementation)t.getConnection(); while (t.getRegionLocation(rk).getPort() != sn.getPort()){ TEST_UTIL.getHBaseAdmin().move(t.getRegionLocation(rk).getRegionInfo(). getEncodedNameAsBytes(), Bytes.toBytes(sn.toString())); while(TEST_UTIL.getHBaseCluster().getMaster().getAssignmentManager(). getRegionStates().isRegionsInTransition()){ Thread.sleep(1); } hci.clearRegionCache(tn); } Assert.assertNotNull(hci.clusterStatusListener); TEST_UTIL.assertRegionOnServer(t.getRegionLocation(rk).getRegionInfo(), sn, 20000); Put p1 = new Put(rk); p1.add(cf, "qual".getBytes(), "val".getBytes()); t.put(p1); rs.getRegionServer().abort("I'm dead"); // We want the status to be updated. That's a least 10 second TEST_UTIL.waitFor(40000, 1000, true, new Waiter.Predicate<Exception>() { @Override public boolean evaluate() throws Exception { return TEST_UTIL.getHBaseCluster().getMaster().getServerManager(). getDeadServers().isDeadServer(sn); } }); TEST_UTIL.waitFor(40000, 1000, true, new Waiter.Predicate<Exception>() { @Override public boolean evaluate() throws Exception { return hci.clusterStatusListener.isDeadServer(sn); } }); t.close(); hci.getClient(sn); // will throw an exception: RegionServerStoppedException }
/** * Test that the connection to the dead server is cut immediately when we receive the * notification. * @throws Exception */ @Test public void testConnectionCut() throws Exception { String tableName = "HCM-testConnectionCut"; TEST_UTIL.createTable(tableName.getBytes(), FAM_NAM).close(); boolean previousBalance = TEST_UTIL.getHBaseAdmin().setBalancerRunning(false, true); Configuration c2 = new Configuration(TEST_UTIL.getConfiguration()); // We want to work on a separate connection. c2.set(HConstants.HBASE_CLIENT_INSTANCE_ID, String.valueOf(-1)); c2.setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 1); c2.setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 30 * 1000); HTable table = new HTable(c2, tableName); Put p = new Put(FAM_NAM); p.add(FAM_NAM, FAM_NAM, FAM_NAM); table.put(p); final HConnectionImplementation hci = (HConnectionImplementation)table.getConnection(); final HRegionLocation loc = table.getRegionLocation(FAM_NAM); Get get = new Get(FAM_NAM); Assert.assertNotNull(table.get(get)); get = new Get(FAM_NAM); get.setFilter(new BlockingFilter()); // This thread will mark the server as dead while we're waiting during a get. Thread t = new Thread() { @Override public void run() { synchronized (syncBlockingFilter) { try { syncBlockingFilter.wait(); } catch (InterruptedException e) { throw new RuntimeException(e); } } hci.clusterStatusListener.deadServerHandler.newDead(loc.getServerName()); } }; t.start(); try { table.get(get); Assert.fail(); } catch (IOException expected) { LOG.debug("Received: " + expected); Assert.assertFalse(expected instanceof SocketTimeoutException); Assert.assertFalse(syncBlockingFilter.get()); } finally { syncBlockingFilter.set(true); t.join(); HConnectionManager.getConnection(c2).close(); TEST_UTIL.getHBaseAdmin().setBalancerRunning(previousBalance, true); } table.close(); }
/** * Test that stale cache updates don't override newer cached values. */ @Test(timeout = 60000) public void testCacheSeqNums() throws Exception{ HTable table = TEST_UTIL.createTable(TABLE_NAME2, FAM_NAM); TEST_UTIL.createMultiRegions(table, FAM_NAM); Put put = new Put(ROW); put.add(FAM_NAM, ROW, ROW); table.put(put); ConnectionManager.HConnectionImplementation conn = (ConnectionManager.HConnectionImplementation)table.getConnection(); HRegionLocation location = conn.getCachedLocation(TABLE_NAME2, ROW); assertNotNull(location); ServerName anySource = ServerName.valueOf(location.getHostname(), location.getPort() - 1, 0L); // Same server as already in cache reporting - overwrites any value despite seqNum. int nextPort = location.getPort() + 1; conn.updateCachedLocation(location.getRegionInfo(), location.getServerName(), ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() - 1); location = conn.getCachedLocation(TABLE_NAME2, ROW); Assert.assertEquals(nextPort, location.getPort()); // No source specified - same. nextPort = location.getPort() + 1; conn.updateCachedLocation(location.getRegionInfo(), location.getServerName(), ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() - 1); location = conn.getCachedLocation(TABLE_NAME2, ROW); Assert.assertEquals(nextPort, location.getPort()); // Higher seqNum - overwrites lower seqNum. nextPort = location.getPort() + 1; conn.updateCachedLocation(location.getRegionInfo(), anySource, ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() + 1); location = conn.getCachedLocation(TABLE_NAME2, ROW); Assert.assertEquals(nextPort, location.getPort()); // Lower seqNum - does not overwrite higher seqNum. nextPort = location.getPort() + 1; conn.updateCachedLocation(location.getRegionInfo(), anySource, ServerName.valueOf("127.0.0.1", nextPort, 0), location.getSeqNum() - 1); location = conn.getCachedLocation(TABLE_NAME2, ROW); Assert.assertEquals(nextPort - 1, location.getPort()); table.close(); }