View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  package org.apache.hadoop.hbase.client;
19  
20  import com.google.common.util.concurrent.Uninterruptibles;
21  import java.io.IOException;
22  import java.util.ArrayList;
23  import java.util.List;
24  import java.util.concurrent.ExecutorService;
25  import java.util.concurrent.TimeUnit;
26  import java.util.concurrent.atomic.AtomicInteger;
27  import org.apache.hadoop.conf.Configuration;
28  import org.apache.hadoop.hbase.HBaseConfiguration;
29  import org.apache.hadoop.hbase.ServerName;
30  import org.apache.hadoop.hbase.TableName;
31  import org.apache.hadoop.hbase.Waiter;
32  import org.apache.hadoop.hbase.testclassification.ClientTests;
33  import org.apache.hadoop.hbase.testclassification.SmallTests;
34  import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
35  import org.junit.Assert;
36  import org.junit.Test;
37  import org.junit.experimental.categories.Category;
38  
39  @Category({ClientTests.class, SmallTests.class})
40  public class TestMasterAddressRefresher {
41  
42    static class DummyConnection implements Connection {
43      private final Configuration conf;
44  
45      DummyConnection(Configuration conf) {
46        this.conf = conf;
47      }
48  
49      @Override
50      public Configuration getConfiguration() {
51        return conf;
52      }
53  
54      @Override
55      public Table getTable(TableName tableName) throws IOException {
56        return null;
57      }
58  
59      @Override
60      public Table getTable(TableName tableName, ExecutorService pool) throws IOException {
61        return null;
62      }
63  
64      @Override
65      public BufferedMutator getBufferedMutator(TableName tableName) throws IOException {
66        return null;
67      }
68  
69      @Override
70      public BufferedMutator getBufferedMutator(BufferedMutatorParams params) throws IOException {
71        return null;
72      }
73  
74      @Override
75      public RegionLocator getRegionLocator(TableName tableName) throws IOException {
76        return null;
77      }
78  
79      @Override
80      public Admin getAdmin() throws IOException {
81        return null;
82      }
83  
84      @Override
85      public String getClusterId() throws IOException {
86        return null;
87      }
88  
89      @Override
90      public void close() throws IOException {
91  
92      }
93  
94      @Override
95      public boolean isClosed() {
96        return false;
97      }
98  
99      @Override
100     public void abort(String why, Throwable e) {
101 
102     }
103 
104     @Override
105     public boolean isAborted() {
106       return false;
107     }
108   }
109 
110   private static class DummyMasterRegistry extends MasterRegistry {
111 
112     private final AtomicInteger getMastersCallCounter = new AtomicInteger(0);
113     private final List<Long> callTimeStamps = new ArrayList<>();
114 
115     @Override
116     public void init(Connection connection) throws IOException {
117       super.init(connection);
118     }
119 
120     @Override
121     List<ServerName> getMasters() {
122       getMastersCallCounter.incrementAndGet();
123       callTimeStamps.add(EnvironmentEdgeManager.currentTime());
124       return new ArrayList<>();
125     }
126 
127     public int getMastersCount() {
128       return getMastersCallCounter.get();
129     }
130 
131     public List<Long> getCallTimeStamps() {
132       return callTimeStamps;
133     }
134   }
135 
136   @Test
137   public void testPeriodicMasterEndPointRefresh() throws IOException {
138     Configuration conf = HBaseConfiguration.create();
139     // Refresh every 1 second.
140     conf.setLong(MasterAddressRefresher.PERIODIC_REFRESH_INTERVAL_SECS, 1);
141     conf.setLong(MasterAddressRefresher.MIN_SECS_BETWEEN_REFRESHES, 0);
142     final DummyMasterRegistry registry = new DummyMasterRegistry();
143     registry.init(new DummyConnection(conf));
144     // Wait for > 3 seconds to see that at least 3 getMasters() RPCs have been made.
145     Waiter.waitFor(
146         conf, 5000, new Waiter.Predicate<Exception>() {
147           @Override
148           public boolean evaluate() throws Exception {
149             return registry.getMastersCount() > 3;
150           }
151         });
152   }
153 
154   @Test
155   public void testDurationBetweenRefreshes() throws IOException {
156     Configuration conf = HBaseConfiguration.create();
157     // Disable periodic refresh
158     conf.setLong(MasterAddressRefresher.PERIODIC_REFRESH_INTERVAL_SECS, Integer.MAX_VALUE);
159     // A minimum duration of 1s between refreshes
160     conf.setLong(MasterAddressRefresher.MIN_SECS_BETWEEN_REFRESHES, 1);
161     DummyMasterRegistry registry = new DummyMasterRegistry();
162     registry.init(new DummyConnection(conf));
163     // Issue a ton of manual refreshes.
164     for (int i = 0; i < 10000; i++) {
165       registry.masterAddressRefresher.refreshNow();
166       Uninterruptibles.sleepUninterruptibly(1, TimeUnit.MILLISECONDS);
167     }
168     // Overall wait time is 10000 ms, so the number of requests should be <=10
169     List<Long> callTimeStamps = registry.getCallTimeStamps();
170     // Actual calls to getMasters() should be much lower than the refresh count.
171     Assert.assertTrue(
172         String.valueOf(registry.getMastersCount()), registry.getMastersCount() <= 20);
173     Assert.assertTrue(callTimeStamps.size() > 0);
174     // Verify that the delta between subsequent RPCs is at least 1sec as configured.
175     for (int i = 1; i < callTimeStamps.size() - 1; i++) {
176       long delta = callTimeStamps.get(i) - callTimeStamps.get(i - 1);
177       // Few ms cushion to account for any env jitter.
178       Assert.assertTrue(callTimeStamps.toString(), delta > 990);
179     }
180   }
181 }