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