1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.zookeeper;
19
20 import java.util.ArrayList;
21 import java.util.Collections;
22 import java.util.Comparator;
23 import java.util.List;
24 import org.apache.hadoop.hbase.classification.InterfaceAudience;
25 import org.apache.hadoop.hbase.Abortable;
26 import org.apache.hadoop.hbase.HConstants;
27 import org.apache.hadoop.hbase.ServerName;
28 import org.apache.hadoop.hbase.exceptions.DeserializationException;
29 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
30 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
31 import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos;
32 import org.apache.zookeeper.KeeperException;
33 import org.apache.zookeeper.data.Stat;
34
35 import java.io.IOException;
36 import java.io.InterruptedIOException;
37 import com.google.protobuf.InvalidProtocolBufferException;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 @InterfaceAudience.Private
58 public class MasterAddressTracker extends ZooKeeperNodeTracker {
59
60
61
62
63
64
65
66
67
68
69
70 public MasterAddressTracker(ZooKeeperWatcher watcher, Abortable abortable) {
71 super(watcher, watcher.getMasterAddressZNode(), abortable);
72 }
73
74
75
76
77
78 public static List<ServerName> getBackupMastersAndRenewWatch(
79 ZooKeeperWatcher watcher) {
80
81 List<String> backupMasterStrings;
82 try {
83 backupMasterStrings = ZKUtil.listChildrenAndWatchForNewChildren(
84 watcher, watcher.backupMasterAddressesZNode);
85 } catch (KeeperException e) {
86 LOG.warn(watcher.prefix("Unable to list backup servers"), e);
87 backupMasterStrings = null;
88 }
89
90 List<ServerName> backupMasters = new ArrayList<>();
91 if (backupMasterStrings != null && !backupMasterStrings.isEmpty()) {
92 for (String s: backupMasterStrings) {
93 try {
94 byte [] bytes;
95 try {
96 bytes = ZKUtil.getData(watcher, ZKUtil.joinZNode(
97 watcher.backupMasterAddressesZNode, s));
98 } catch (InterruptedException e) {
99 throw new InterruptedIOException("Thread interrupted.");
100 }
101 if (bytes != null) {
102 ServerName sn;
103 try {
104 sn = ServerName.parseFrom(bytes);
105 } catch (DeserializationException e) {
106 LOG.warn("Failed parse, skipping registering backup server", e);
107 continue;
108 }
109 backupMasters.add(sn);
110 }
111 } catch (KeeperException | InterruptedIOException e) {
112 LOG.warn(watcher.prefix("Unable to get information about " +
113 "backup servers"), e);
114 }
115 }
116 Collections.sort(backupMasters, new Comparator<ServerName>() {
117 @Override
118 public int compare(ServerName s1, ServerName s2) {
119 return s1.getServerName().compareTo(s2.getServerName());
120 }});
121 }
122 return backupMasters;
123 }
124
125
126
127
128
129
130 public ServerName getMasterAddress() {
131 return getMasterAddress(false);
132 }
133
134
135
136
137
138
139 public int getMasterInfoPort() {
140 try {
141 final ZooKeeperProtos.Master master = parse(this.getData(false));
142 if (master == null) {
143 return 0;
144 }
145 return master.getInfoPort();
146 } catch (DeserializationException e) {
147 LOG.warn("Failed parse master zk node data", e);
148 return 0;
149 }
150 }
151
152
153
154
155
156
157 public int getBackupMasterInfoPort(final ServerName sn) {
158 String backupZNode = ZKUtil.joinZNode(watcher.backupMasterAddressesZNode, sn.toString());
159 try {
160 byte[] data = ZKUtil.getData(watcher, backupZNode);
161 final ZooKeeperProtos.Master backup = parse(data);
162 if (backup == null) {
163 return 0;
164 }
165 return backup.getInfoPort();
166 } catch (Exception e) {
167 LOG.warn("Failed to get backup master: " + sn + "'s info port.", e);
168 return 0;
169 }
170 }
171
172
173
174
175
176
177
178
179
180 public ServerName getMasterAddress(final boolean refresh) {
181 try {
182 return ServerName.parseFrom(super.getData(refresh));
183 } catch (DeserializationException e) {
184 LOG.warn("Failed parse", e);
185 return null;
186 }
187 }
188
189
190
191
192
193
194
195
196
197
198
199 public static ServerName getMasterAddress(final ZooKeeperWatcher zkw)
200 throws KeeperException, IOException {
201 byte [] data;
202 try {
203 data = ZKUtil.getData(zkw, zkw.getMasterAddressZNode());
204 } catch (InterruptedException e) {
205 throw new InterruptedIOException();
206 }
207
208 if (data == null){
209 throw new IOException("Can't get master address from ZooKeeper; znode data == null");
210 }
211 try {
212 return ServerName.parseFrom(data);
213 } catch (DeserializationException e) {
214 KeeperException ke = new KeeperException.DataInconsistencyException();
215 ke.initCause(e);
216 throw ke;
217 }
218 }
219
220
221
222
223
224
225
226
227
228
229
230
231 public static int getMasterInfoPort(final ZooKeeperWatcher zkw) throws KeeperException,
232 IOException {
233 byte[] data;
234 try {
235 data = ZKUtil.getData(zkw, zkw.getMasterAddressZNode());
236 } catch (InterruptedException e) {
237 throw new InterruptedIOException();
238 }
239
240 if (data == null) {
241 throw new IOException("Can't get master address from ZooKeeper; znode data == null");
242 }
243 try {
244 return parse(data).getInfoPort();
245 } catch (DeserializationException e) {
246 KeeperException ke = new KeeperException.DataInconsistencyException();
247 ke.initCause(e);
248 throw ke;
249 }
250 }
251
252
253
254
255
256
257
258
259
260
261
262
263 public static boolean setMasterAddress(final ZooKeeperWatcher zkw,
264 final String znode, final ServerName master, int infoPort)
265 throws KeeperException {
266 return ZKUtil.createEphemeralNodeAndWatch(zkw, znode, toByteArray(master, infoPort));
267 }
268
269
270
271
272
273 public boolean hasMaster() {
274 return super.getData(false) != null;
275 }
276
277
278
279
280
281
282 static byte[] toByteArray(final ServerName sn, int infoPort) {
283 ZooKeeperProtos.Master.Builder mbuilder = ZooKeeperProtos.Master.newBuilder();
284 HBaseProtos.ServerName.Builder snbuilder = HBaseProtos.ServerName.newBuilder();
285 snbuilder.setHostName(sn.getHostname());
286 snbuilder.setPort(sn.getPort());
287 snbuilder.setStartCode(sn.getStartcode());
288 mbuilder.setMaster(snbuilder.build());
289 mbuilder.setRpcVersion(HConstants.RPC_CURRENT_VERSION);
290 mbuilder.setInfoPort(infoPort);
291 return ProtobufUtil.prependPBMagic(mbuilder.build().toByteArray());
292 }
293
294
295
296
297
298
299 public static ZooKeeperProtos.Master parse(byte[] data) throws DeserializationException {
300 if (data == null) {
301 return null;
302 }
303 int prefixLen = ProtobufUtil.lengthOfPBMagic();
304 try {
305 return ZooKeeperProtos.Master.PARSER.parseFrom(data, prefixLen, data.length - prefixLen);
306 } catch (InvalidProtocolBufferException e) {
307 throw new DeserializationException(e);
308 }
309 }
310
311
312
313
314
315 public static boolean deleteIfEquals(ZooKeeperWatcher zkw, final String content) {
316 if (content == null){
317 throw new IllegalArgumentException("Content must not be null");
318 }
319
320 try {
321 Stat stat = new Stat();
322 byte[] data = ZKUtil.getDataNoWatch(zkw, zkw.getMasterAddressZNode(), stat);
323 ServerName sn = ServerName.parseFrom(data);
324 if (sn != null && content.equals(sn.toString())) {
325 return (ZKUtil.deleteNode(zkw, zkw.getMasterAddressZNode(), stat.getVersion()));
326 }
327 } catch (KeeperException e) {
328 LOG.warn("Can't get or delete the master znode", e);
329 } catch (DeserializationException e) {
330 LOG.warn("Can't get or delete the master znode", e);
331 }
332
333 return false;
334 }
335 }