1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.client;
19
20 import com.google.common.base.Preconditions;
21 import com.google.common.util.concurrent.ThreadFactoryBuilder;
22 import java.io.Closeable;
23 import java.io.IOException;
24 import java.util.HashSet;
25 import java.util.Set;
26 import java.util.concurrent.ExecutorService;
27 import java.util.concurrent.Executors;
28 import java.util.concurrent.TimeUnit;
29 import org.apache.hadoop.conf.Configuration;
30 import org.apache.hadoop.hbase.ServerName;
31 import org.apache.hadoop.hbase.classification.InterfaceAudience;
32 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ClientMetaService;
37
38
39
40
41
42
43
44
45
46 @InterfaceAudience.Private
47 public class MasterAddressRefresher implements Closeable {
48 private static final Logger LOG = LoggerFactory.getLogger(MasterAddressRefresher.class);
49 public static final String PERIODIC_REFRESH_INTERVAL_SECS =
50 "hbase.client.master_registry.refresh_interval_secs";
51 private static final int PERIODIC_REFRESH_INTERVAL_SECS_DEFAULT = 300;
52 public static final String MIN_SECS_BETWEEN_REFRESHES =
53 "hbase.client.master_registry.min_secs_between_refreshes";
54 private static final int MIN_SECS_BETWEEN_REFRESHES_DEFAULT = 60;
55
56 private final ExecutorService pool;
57 private final MasterRegistry registry;
58 private final long periodicRefreshMs;
59 private final long timeBetweenRefreshesMs;
60 private final Object refreshMasters = new Object();
61
62 @Override
63 public void close() {
64 pool.shutdownNow();
65 }
66
67
68
69
70
71 private class RefreshThread implements Runnable {
72 @Override
73 public void run() {
74 long lastRpcTs = 0;
75 while (!Thread.interrupted()) {
76 try {
77
78
79
80 synchronized (refreshMasters) {
81 refreshMasters.wait(periodicRefreshMs);
82 }
83 long currentTs = EnvironmentEdgeManager.currentTime();
84 if (lastRpcTs != 0 && currentTs - lastRpcTs <= timeBetweenRefreshesMs) {
85 continue;
86 }
87 lastRpcTs = currentTs;
88 LOG.debug("Attempting to refresh master address end points.");
89 Set<ServerName> newMasters = new HashSet<>(registry.getMasters());
90 registry.populateMasterStubs(newMasters);
91 LOG.debug("Finished refreshing master end points. {}", newMasters);
92 } catch (InterruptedException e) {
93 LOG.debug("Interrupted during wait, aborting refresh-masters-thread.", e);
94 break;
95 } catch (IOException e) {
96 LOG.debug("Error populating latest list of masters.", e);
97 }
98 }
99 LOG.info("Master end point refresher loop exited.");
100 }
101 }
102
103 MasterAddressRefresher(Configuration conf, MasterRegistry registry) {
104 pool = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder()
105 .setNameFormat("master-registry-refresh-end-points").setDaemon(true).build());
106 periodicRefreshMs = TimeUnit.SECONDS.toMillis(conf.getLong(PERIODIC_REFRESH_INTERVAL_SECS,
107 PERIODIC_REFRESH_INTERVAL_SECS_DEFAULT));
108 timeBetweenRefreshesMs = TimeUnit.SECONDS.toMillis(conf.getLong(MIN_SECS_BETWEEN_REFRESHES,
109 MIN_SECS_BETWEEN_REFRESHES_DEFAULT));
110 Preconditions.checkArgument(periodicRefreshMs > 0);
111 Preconditions.checkArgument(timeBetweenRefreshesMs < periodicRefreshMs);
112 this.registry = registry;
113 pool.submit(new RefreshThread());
114 }
115
116
117
118
119
120 void refreshNow() {
121 synchronized (refreshMasters) {
122 refreshMasters.notify();
123 }
124 }
125 }