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