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.io.EOFException;
21 import java.io.IOException;
22 import java.net.ConnectException;
23 import java.net.NoRouteToHostException;
24 import java.net.SocketException;
25 import java.net.SocketTimeoutException;
26 import java.net.UnknownHostException;
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.hadoop.conf.Configuration;
33 import org.apache.hadoop.hbase.HConstants;
34 import org.apache.hadoop.hbase.HRegionInfo;
35 import org.apache.hadoop.hbase.NotAllMetaRegionsOnlineException;
36 import org.apache.hadoop.hbase.ServerName;
37 import org.apache.hadoop.hbase.classification.InterfaceAudience;
38 import org.apache.hadoop.hbase.client.ClusterConnection;
39 import org.apache.hadoop.hbase.client.Connection;
40 import org.apache.hadoop.hbase.client.HConnection;
41 import org.apache.hadoop.hbase.client.RegionReplicaUtil;
42 import org.apache.hadoop.hbase.client.RetriesExhaustedException;
43 import org.apache.hadoop.hbase.exceptions.DeserializationException;
44 import org.apache.hadoop.hbase.ipc.FailedServerException;
45 import org.apache.hadoop.hbase.ipc.PayloadCarryingRpcController;
46 import org.apache.hadoop.hbase.ipc.ServerNotRunningYetException;
47 import org.apache.hadoop.hbase.master.RegionState;
48 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
49 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos;
50 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.AdminService;
51 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
52 import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos;
53 import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos.MetaRegionServer;
54 import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;
55 import org.apache.hadoop.hbase.util.Bytes;
56 import org.apache.hadoop.hbase.util.Pair;
57 import org.apache.hadoop.ipc.RemoteException;
58 import org.apache.zookeeper.KeeperException;
59
60 import com.google.protobuf.InvalidProtocolBufferException;
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77 @InterfaceAudience.Private
78 public class MetaTableLocator {
79 private static final Log LOG = LogFactory.getLog(MetaTableLocator.class);
80
81
82 private volatile boolean stopped = false;
83
84
85
86
87
88 public boolean isLocationAvailable(ZooKeeperWatcher zkw) {
89 return getMetaRegionLocation(zkw) != null;
90 }
91
92
93
94
95
96 public List<Pair<HRegionInfo, ServerName>> getMetaRegionsAndLocations(ZooKeeperWatcher zkw) {
97 return getMetaRegionsAndLocations(zkw, HRegionInfo.DEFAULT_REPLICA_ID);
98 }
99
100
101
102
103
104
105
106 public List<Pair<HRegionInfo, ServerName>> getMetaRegionsAndLocations(ZooKeeperWatcher zkw,
107 int replicaId) {
108 ServerName serverName = getMetaRegionLocation(zkw, replicaId);
109 List<Pair<HRegionInfo, ServerName>> list = new ArrayList<Pair<HRegionInfo, ServerName>>();
110 list.add(new Pair<HRegionInfo, ServerName>(RegionReplicaUtil.getRegionInfoForReplica(
111 HRegionInfo.FIRST_META_REGIONINFO, replicaId), serverName));
112 return list;
113 }
114
115
116
117
118
119 public List<HRegionInfo> getMetaRegions(ZooKeeperWatcher zkw) {
120 return getMetaRegions(zkw, HRegionInfo.DEFAULT_REPLICA_ID);
121 }
122
123
124
125
126
127
128
129 public List<HRegionInfo> getMetaRegions(ZooKeeperWatcher zkw, int replicaId) {
130 List<Pair<HRegionInfo, ServerName>> result;
131 result = getMetaRegionsAndLocations(zkw, replicaId);
132 return getListOfHRegionInfos(result);
133 }
134
135 private List<HRegionInfo> getListOfHRegionInfos(
136 final List<Pair<HRegionInfo, ServerName>> pairs) {
137 if (pairs == null || pairs.isEmpty()) return null;
138 List<HRegionInfo> result = new ArrayList<HRegionInfo>(pairs.size());
139 for (Pair<HRegionInfo, ServerName> pair: pairs) {
140 result.add(pair.getFirst());
141 }
142 return result;
143 }
144
145
146
147
148
149
150 public ServerName getMetaRegionLocation(final ZooKeeperWatcher zkw) {
151 try {
152 RegionState state = getMetaRegionState(zkw);
153 return state.isOpened() ? state.getServerName() : null;
154 } catch (KeeperException ke) {
155 return null;
156 }
157 }
158
159
160
161
162
163
164
165 public ServerName getMetaRegionLocation(final ZooKeeperWatcher zkw, int replicaId) {
166 try {
167 RegionState state = getMetaRegionState(zkw, replicaId);
168 return state.isOpened() ? state.getServerName() : null;
169 } catch (KeeperException ke) {
170 return null;
171 }
172 }
173
174
175
176
177
178
179
180
181
182
183
184
185
186 public ServerName waitMetaRegionLocation(ZooKeeperWatcher zkw, long timeout)
187 throws InterruptedException, NotAllMetaRegionsOnlineException {
188 return waitMetaRegionLocation(zkw, HRegionInfo.DEFAULT_REPLICA_ID, timeout);
189 }
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204 public ServerName waitMetaRegionLocation(ZooKeeperWatcher zkw, int replicaId, long timeout)
205 throws InterruptedException, NotAllMetaRegionsOnlineException {
206 try {
207 if (ZKUtil.checkExists(zkw, zkw.baseZNode) == -1) {
208 String errorMsg = "Check the value configured in 'zookeeper.znode.parent'. "
209 + "There could be a mismatch with the one configured in the master.";
210 LOG.error(errorMsg);
211 throw new IllegalArgumentException(errorMsg);
212 }
213 } catch (KeeperException e) {
214 throw new IllegalStateException("KeeperException while trying to check baseZNode:", e);
215 }
216 ServerName sn = blockUntilAvailable(zkw, replicaId, timeout);
217
218 if (sn == null) {
219 throw new NotAllMetaRegionsOnlineException("Timed out; " + timeout + "ms");
220 }
221
222 return sn;
223 }
224
225
226
227
228
229
230
231
232 public void waitMetaRegionLocation(ZooKeeperWatcher zkw) throws InterruptedException {
233 long startTime = System.currentTimeMillis();
234 while (!stopped) {
235 try {
236 if (waitMetaRegionLocation(zkw, 100) != null) break;
237 long sleepTime = System.currentTimeMillis() - startTime;
238
239 if ((sleepTime + 1) % 10000 == 0) {
240 LOG.warn("Have been waiting for meta to be assigned for " + sleepTime + "ms");
241 }
242 } catch (NotAllMetaRegionsOnlineException e) {
243 if (LOG.isTraceEnabled()) {
244 LOG.trace("hbase:meta still not available, sleeping and retrying." +
245 " Reason: " + e.getMessage());
246 }
247 }
248 }
249 }
250
251
252
253
254
255
256
257
258
259
260
261 public boolean verifyMetaRegionLocation(HConnection hConnection,
262 ZooKeeperWatcher zkw, final long timeout)
263 throws InterruptedException, IOException {
264 return verifyMetaRegionLocation(hConnection, zkw, timeout, HRegionInfo.DEFAULT_REPLICA_ID);
265 }
266
267
268
269
270
271
272
273
274
275
276
277 public boolean verifyMetaRegionLocation(HConnection hConnection,
278 ZooKeeperWatcher zkw, final long timeout, int replicaId)
279 throws InterruptedException, IOException {
280 AdminProtos.AdminService.BlockingInterface service = null;
281 try {
282 service = getMetaServerConnection(hConnection, zkw, timeout, replicaId);
283 } catch (NotAllMetaRegionsOnlineException e) {
284
285 } catch (ServerNotRunningYetException e) {
286
287 } catch (UnknownHostException e) {
288
289 } catch (RegionServerStoppedException e) {
290
291 }
292 return (service != null) && verifyRegionLocation(hConnection, service,
293 getMetaRegionLocation(zkw, replicaId), RegionReplicaUtil.getRegionInfoForReplica(
294 HRegionInfo.FIRST_META_REGIONINFO, replicaId).getRegionName());
295 }
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312 private boolean verifyRegionLocation(final Connection connection,
313 AdminService.BlockingInterface hostingServer, final ServerName address,
314 final byte [] regionName)
315 throws IOException {
316 if (hostingServer == null) {
317 LOG.info("Passed hostingServer is null");
318 return false;
319 }
320 Throwable t;
321 PayloadCarryingRpcController controller = null;
322 if (connection instanceof ClusterConnection) {
323 controller = ((ClusterConnection) connection).getRpcControllerFactory().newController();
324 }
325 try {
326
327 return ProtobufUtil.getRegionInfo(controller, hostingServer, regionName) != null;
328 } catch (ConnectException e) {
329 t = e;
330 } catch (RetriesExhaustedException e) {
331 t = e;
332 } catch (RemoteException e) {
333 IOException ioe = e.unwrapRemoteException();
334 t = ioe;
335 } catch (IOException e) {
336 Throwable cause = e.getCause();
337 if (cause != null && cause instanceof EOFException) {
338 t = cause;
339 } else if (cause != null && cause.getMessage() != null
340 && cause.getMessage().contains("Connection reset")) {
341 t = cause;
342 } else {
343 t = e;
344 }
345 }
346 LOG.info("Failed verification of " + Bytes.toStringBinary(regionName) +
347 " at address=" + address + ", exception=" + t.getMessage());
348 return false;
349 }
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364 private AdminService.BlockingInterface getMetaServerConnection(HConnection hConnection,
365 ZooKeeperWatcher zkw, long timeout, int replicaId)
366 throws InterruptedException, NotAllMetaRegionsOnlineException, IOException {
367 return getCachedConnection(hConnection, waitMetaRegionLocation(zkw, replicaId, timeout));
368 }
369
370
371
372
373
374
375
376
377 @SuppressWarnings("deprecation")
378 private static AdminService.BlockingInterface getCachedConnection(HConnection hConnection,
379 ServerName sn)
380 throws IOException {
381 if (sn == null) {
382 return null;
383 }
384 AdminService.BlockingInterface service = null;
385 try {
386 service = hConnection.getAdmin(sn);
387 } catch (RetriesExhaustedException e) {
388 if (e.getCause() != null && e.getCause() instanceof ConnectException) {
389
390 } else {
391 throw e;
392 }
393 } catch (SocketTimeoutException e) {
394 LOG.debug("Timed out connecting to " + sn);
395 } catch (NoRouteToHostException e) {
396 LOG.debug("Connecting to " + sn, e);
397 } catch (SocketException e) {
398 LOG.debug("Exception connecting to " + sn);
399 } catch (UnknownHostException e) {
400 LOG.debug("Unknown host exception connecting to " + sn);
401 } catch (FailedServerException e) {
402 if (LOG.isDebugEnabled()) {
403 LOG.debug("Server " + sn + " is in failed server list.");
404 }
405 } catch (IOException ioe) {
406 Throwable cause = ioe.getCause();
407 if (ioe instanceof ConnectException) {
408
409 } else if (cause != null && cause instanceof EOFException) {
410
411 } else if (cause != null && cause.getMessage() != null &&
412 cause.getMessage().toLowerCase().contains("connection reset")) {
413
414 } else {
415 throw ioe;
416 }
417
418 }
419 return service;
420 }
421
422
423
424
425
426
427
428
429
430 public static void setMetaLocation(ZooKeeperWatcher zookeeper,
431 ServerName serverName, RegionState.State state) throws KeeperException {
432 setMetaLocation(zookeeper, serverName, HRegionInfo.DEFAULT_REPLICA_ID, state);
433 }
434
435
436
437
438
439
440
441
442
443
444 public static void setMetaLocation(ZooKeeperWatcher zookeeper,
445 ServerName serverName, int replicaId, RegionState.State state) throws KeeperException {
446 LOG.info("Setting hbase:meta region location in ZooKeeper as " + serverName);
447
448
449 MetaRegionServer pbrsr = MetaRegionServer.newBuilder()
450 .setServer(ProtobufUtil.toServerName(serverName))
451 .setRpcVersion(HConstants.RPC_CURRENT_VERSION)
452 .setState(state.convert()).build();
453 byte[] data = ProtobufUtil.prependPBMagic(pbrsr.toByteArray());
454 try {
455 ZKUtil.setData(zookeeper, zookeeper.getZNodeForReplica(replicaId), data);
456 } catch(KeeperException.NoNodeException nne) {
457 if (replicaId == HRegionInfo.DEFAULT_REPLICA_ID) {
458 LOG.debug("META region location doesn't exist, create it");
459 } else {
460 LOG.debug("META region location doesn't exist for replicaId " + replicaId +
461 ", create it");
462 }
463 ZKUtil.createAndWatch(zookeeper, zookeeper.getZNodeForReplica(replicaId), data);
464 }
465 }
466
467
468
469
470 public static RegionState getMetaRegionState(ZooKeeperWatcher zkw) throws KeeperException {
471 return getMetaRegionState(zkw, HRegionInfo.DEFAULT_REPLICA_ID);
472 }
473
474
475
476
477
478
479
480
481 public static RegionState getMetaRegionState(ZooKeeperWatcher zkw, int replicaId)
482 throws KeeperException {
483 RegionState.State state = RegionState.State.OPEN;
484 ServerName serverName = null;
485 try {
486 byte[] data = ZKUtil.getData(zkw, zkw.getZNodeForReplica(replicaId));
487 if (data != null && data.length > 0 && ProtobufUtil.isPBMagicPrefix(data)) {
488 try {
489 int prefixLen = ProtobufUtil.lengthOfPBMagic();
490 ZooKeeperProtos.MetaRegionServer rl =
491 ZooKeeperProtos.MetaRegionServer.PARSER.parseFrom
492 (data, prefixLen, data.length - prefixLen);
493 if (rl.hasState()) {
494 state = RegionState.State.convert(rl.getState());
495 }
496 HBaseProtos.ServerName sn = rl.getServer();
497 serverName = ServerName.valueOf(
498 sn.getHostName(), sn.getPort(), sn.getStartCode());
499 } catch (InvalidProtocolBufferException e) {
500 throw new DeserializationException("Unable to parse meta region location");
501 }
502 } else {
503
504 serverName = ServerName.parseFrom(data);
505 }
506 } catch (DeserializationException e) {
507 throw ZKUtil.convert(e);
508 } catch (InterruptedException e) {
509 Thread.currentThread().interrupt();
510 }
511 if (serverName == null) {
512 state = RegionState.State.OFFLINE;
513 }
514 return new RegionState(
515 RegionReplicaUtil.getRegionInfoForReplica(HRegionInfo.FIRST_META_REGIONINFO, replicaId),
516 state, serverName);
517 }
518
519
520
521
522
523
524 public void deleteMetaLocation(ZooKeeperWatcher zookeeper)
525 throws KeeperException {
526 deleteMetaLocation(zookeeper, HRegionInfo.DEFAULT_REPLICA_ID);
527 }
528
529 public void deleteMetaLocation(ZooKeeperWatcher zookeeper, int replicaId)
530 throws KeeperException {
531 if (replicaId == HRegionInfo.DEFAULT_REPLICA_ID) {
532 LOG.info("Deleting hbase:meta region location in ZooKeeper");
533 } else {
534 LOG.info("Deleting hbase:meta for " + replicaId + " region location in ZooKeeper");
535 }
536 try {
537
538 ZKUtil.deleteNode(zookeeper, zookeeper.getZNodeForReplica(replicaId));
539 } catch(KeeperException.NoNodeException nne) {
540
541 }
542 }
543
544
545
546
547
548
549
550
551
552 public List<ServerName> blockUntilAvailable(final ZooKeeperWatcher zkw,
553 final long timeout, Configuration conf)
554 throws InterruptedException {
555 int numReplicasConfigured = 1;
556
557 List<ServerName> servers = new ArrayList<ServerName>();
558
559
560 ServerName server = blockUntilAvailable(zkw, timeout);
561 if (server == null) return null;
562 servers.add(server);
563
564 try {
565 List<String> metaReplicaNodes = zkw.getMetaReplicaNodes();
566 numReplicasConfigured = metaReplicaNodes.size();
567 } catch (KeeperException e) {
568 LOG.warn("Got ZK exception " + e);
569 }
570 for (int replicaId = 1; replicaId < numReplicasConfigured; replicaId++) {
571
572 servers.add(getMetaRegionLocation(zkw, replicaId));
573 }
574 return servers;
575 }
576
577
578
579
580
581
582
583
584 public ServerName blockUntilAvailable(final ZooKeeperWatcher zkw,
585 final long timeout)
586 throws InterruptedException {
587 return blockUntilAvailable(zkw, HRegionInfo.DEFAULT_REPLICA_ID, timeout);
588 }
589
590
591
592
593
594
595
596
597
598 public ServerName blockUntilAvailable(final ZooKeeperWatcher zkw, int replicaId,
599 final long timeout)
600 throws InterruptedException {
601 if (timeout < 0) throw new IllegalArgumentException();
602 if (zkw == null) throw new IllegalArgumentException();
603 long startTime = System.currentTimeMillis();
604 ServerName sn = null;
605 while (true) {
606 sn = getMetaRegionLocation(zkw, replicaId);
607 if (sn != null || (System.currentTimeMillis() - startTime)
608 > timeout - HConstants.SOCKET_RETRY_WAIT_MS) {
609 break;
610 }
611 Thread.sleep(HConstants.SOCKET_RETRY_WAIT_MS);
612 }
613 return sn;
614 }
615
616
617
618
619
620 public void stop() {
621 if (!stopped) {
622 LOG.debug("Stopping MetaTableLocator");
623 stopped = true;
624 }
625 }
626 }