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 java.io.IOException; 021import java.util.ArrayList; 022import java.util.List; 023import java.util.concurrent.CompletableFuture; 024import java.util.concurrent.TimeUnit; 025import java.util.concurrent.atomic.AtomicInteger; 026import org.apache.hadoop.conf.Configuration; 027import org.apache.hadoop.hbase.HBaseClassTestRule; 028import org.apache.hadoop.hbase.HBaseConfiguration; 029import org.apache.hadoop.hbase.ServerName; 030import org.apache.hadoop.hbase.Waiter; 031import org.apache.hadoop.hbase.testclassification.ClientTests; 032import org.apache.hadoop.hbase.testclassification.SmallTests; 033import org.apache.hadoop.hbase.util.EnvironmentEdgeManager; 034import org.junit.Assert; 035import org.junit.ClassRule; 036import org.junit.Test; 037import org.junit.experimental.categories.Category; 038import org.apache.hbase.thirdparty.com.google.common.util.concurrent.Uninterruptibles; 039 040@Category({ClientTests.class, SmallTests.class}) 041public class TestMasterAddressRefresher { 042 043 @ClassRule 044 public static final HBaseClassTestRule CLASS_RULE = 045 HBaseClassTestRule.forClass(TestMasterAddressRefresher.class); 046 047 private class DummyMasterRegistry extends MasterRegistry { 048 049 private final AtomicInteger getMastersCallCounter = new AtomicInteger(0); 050 private final List<Long> callTimeStamps = new ArrayList<>(); 051 052 DummyMasterRegistry(Configuration conf) throws IOException { 053 super(conf); 054 } 055 056 @Override 057 CompletableFuture<List<ServerName>> getMasters() { 058 getMastersCallCounter.incrementAndGet(); 059 callTimeStamps.add(EnvironmentEdgeManager.currentTime()); 060 return CompletableFuture.completedFuture(new ArrayList<>()); 061 } 062 063 public int getMastersCount() { 064 return getMastersCallCounter.get(); 065 } 066 067 public List<Long> getCallTimeStamps() { 068 return callTimeStamps; 069 } 070 } 071 072 @Test 073 public void testPeriodicMasterEndPointRefresh() throws IOException { 074 Configuration conf = HBaseConfiguration.create(); 075 // Refresh every 1 second. 076 conf.setLong(MasterAddressRefresher.PERIODIC_REFRESH_INTERVAL_SECS, 1); 077 conf.setLong(MasterAddressRefresher.MIN_SECS_BETWEEN_REFRESHES, 0); 078 try (DummyMasterRegistry registry = new DummyMasterRegistry(conf)) { 079 // Wait for > 3 seconds to see that at least 3 getMasters() RPCs have been made. 080 Waiter.waitFor( 081 conf, 5000, (Waiter.Predicate<Exception>) () -> registry.getMastersCount() > 3); 082 } 083 } 084 085 @Test 086 public void testDurationBetweenRefreshes() throws IOException { 087 Configuration conf = HBaseConfiguration.create(); 088 // Disable periodic refresh 089 conf.setLong(MasterAddressRefresher.PERIODIC_REFRESH_INTERVAL_SECS, Integer.MAX_VALUE); 090 // A minimum duration of 1s between refreshes 091 conf.setLong(MasterAddressRefresher.MIN_SECS_BETWEEN_REFRESHES, 1); 092 try (DummyMasterRegistry registry = new DummyMasterRegistry(conf)) { 093 // Issue a ton of manual refreshes. 094 for (int i = 0; i < 10000; i++) { 095 registry.masterAddressRefresher.refreshNow(); 096 Uninterruptibles.sleepUninterruptibly(1, TimeUnit.MILLISECONDS); 097 } 098 // Overall wait time is 10000 ms, so the number of requests should be <=10 099 List<Long> callTimeStamps = registry.getCallTimeStamps(); 100 // Actual calls to getMasters() should be much lower than the refresh count. 101 Assert.assertTrue( 102 String.valueOf(registry.getMastersCount()), registry.getMastersCount() <= 20); 103 Assert.assertTrue(callTimeStamps.size() > 0); 104 // Verify that the delta between subsequent RPCs is at least 1sec as configured. 105 for (int i = 1; i < callTimeStamps.size() - 1; i++) { 106 long delta = callTimeStamps.get(i) - callTimeStamps.get(i - 1); 107 // Few ms cushion to account for any env jitter. 108 Assert.assertTrue(callTimeStamps.toString(), delta > 990); 109 } 110 } 111 112 } 113}