1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.hadoop.hbase.catalog;
21
22 import java.io.EOFException;
23 import java.io.IOException;
24 import java.net.ConnectException;
25 import java.net.NoRouteToHostException;
26 import java.net.SocketException;
27 import java.net.SocketTimeoutException;
28 import java.util.concurrent.atomic.AtomicBoolean;
29
30 import org.apache.commons.logging.Log;
31 import org.apache.commons.logging.LogFactory;
32 import org.apache.hadoop.hbase.Abortable;
33 import org.apache.hadoop.hbase.HRegionInfo;
34 import org.apache.hadoop.hbase.HServerAddress;
35 import org.apache.hadoop.hbase.NotAllMetaRegionsOnlineException;
36 import org.apache.hadoop.hbase.NotServingRegionException;
37 import org.apache.hadoop.hbase.client.HConnection;
38 import org.apache.hadoop.hbase.client.RetriesExhaustedException;
39 import org.apache.hadoop.hbase.ipc.HRegionInterface;
40 import org.apache.hadoop.hbase.util.Bytes;
41 import org.apache.hadoop.hbase.zookeeper.MetaNodeTracker;
42 import org.apache.hadoop.hbase.zookeeper.RootRegionTracker;
43 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
44 import org.apache.hadoop.ipc.RemoteException;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class CatalogTracker {
60 private static final Log LOG = LogFactory.getLog(CatalogTracker.class);
61 private final HConnection connection;
62 private final ZooKeeperWatcher zookeeper;
63 private final RootRegionTracker rootRegionTracker;
64 private final MetaNodeTracker metaNodeTracker;
65 private final AtomicBoolean metaAvailable = new AtomicBoolean(false);
66
67
68
69
70
71
72 private HServerAddress metaLocation;
73 private final int defaultTimeout;
74 private boolean stopped = false;
75
76 public static final byte [] ROOT_REGION =
77 HRegionInfo.ROOT_REGIONINFO.getRegionName();
78 public static final byte [] META_REGION =
79 HRegionInfo.FIRST_META_REGIONINFO.getRegionName();
80
81
82
83
84
85
86
87
88
89 public CatalogTracker(final HConnection connection) throws IOException {
90 this(connection.getZooKeeperWatcher(), connection, connection);
91 }
92
93
94
95
96
97
98
99
100
101
102 public CatalogTracker(final ZooKeeperWatcher zk, final HConnection connection,
103 final Abortable abortable)
104 throws IOException {
105 this(zk, connection, abortable, 0);
106 }
107
108
109
110
111
112
113
114
115
116
117
118 public CatalogTracker(final ZooKeeperWatcher zk, final HConnection connection,
119 final Abortable abortable, final int defaultTimeout)
120 throws IOException {
121 this.zookeeper = zk;
122 this.connection = connection;
123 this.rootRegionTracker = new RootRegionTracker(zookeeper, abortable);
124 this.metaNodeTracker = new MetaNodeTracker(zookeeper, this, abortable);
125 this.defaultTimeout = defaultTimeout;
126 }
127
128
129
130
131
132
133
134
135 public void start() throws IOException, InterruptedException {
136 this.rootRegionTracker.start();
137 this.metaNodeTracker.start();
138 LOG.debug("Starting catalog tracker " + this);
139 }
140
141
142
143
144
145 public void stop() {
146 LOG.debug("Stopping catalog tracker " + this);
147 this.stopped = true;
148 this.rootRegionTracker.stop();
149 this.metaNodeTracker.stop();
150
151 synchronized (this.metaAvailable) {
152 this.metaAvailable.notifyAll();
153 }
154 }
155
156
157
158
159
160
161
162 public HServerAddress getRootLocation() throws InterruptedException {
163 return this.rootRegionTracker.getRootRegionLocation();
164 }
165
166
167
168
169 public HServerAddress getMetaLocation() {
170 return this.metaLocation;
171 }
172
173
174
175
176
177
178 public void waitForRoot()
179 throws InterruptedException {
180 this.rootRegionTracker.blockUntilAvailable();
181 }
182
183
184
185
186
187
188
189
190
191
192
193 HServerAddress waitForRoot(final long timeout)
194 throws InterruptedException, NotAllMetaRegionsOnlineException {
195 HServerAddress address = rootRegionTracker.waitRootRegionLocation(timeout);
196 if (address == null) {
197 throw new NotAllMetaRegionsOnlineException("Timed out; " + timeout + "ms");
198 }
199 return address;
200 }
201
202
203
204
205
206
207
208
209
210
211 public HRegionInterface waitForRootServerConnection(long timeout)
212 throws InterruptedException, NotAllMetaRegionsOnlineException, IOException {
213 return getCachedConnection(waitForRoot(timeout));
214 }
215
216
217
218
219
220
221
222
223
224 public HRegionInterface waitForRootServerConnectionDefault()
225 throws NotAllMetaRegionsOnlineException, IOException {
226 try {
227 return getCachedConnection(waitForRoot(defaultTimeout));
228 } catch (InterruptedException e) {
229 throw new NotAllMetaRegionsOnlineException("Interrupted");
230 }
231 }
232
233
234
235
236
237
238
239
240 private HRegionInterface getRootServerConnection()
241 throws IOException, InterruptedException {
242 HServerAddress address = this.rootRegionTracker.getRootRegionLocation();
243 if (address == null) {
244 return null;
245 }
246 return getCachedConnection(address);
247 }
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265 private HRegionInterface getMetaServerConnection(boolean refresh)
266 throws IOException, InterruptedException {
267 synchronized (metaAvailable) {
268 if (metaAvailable.get()) {
269 HRegionInterface current = getCachedConnection(metaLocation);
270 if (!refresh) {
271 return current;
272 }
273 if (verifyRegionLocation(current, this.metaLocation, META_REGION)) {
274 return current;
275 }
276 resetMetaLocation();
277 }
278 HRegionInterface rootConnection = getRootServerConnection();
279 if (rootConnection == null) {
280 return null;
281 }
282 HServerAddress newLocation = MetaReader.readMetaLocation(rootConnection);
283 if (newLocation == null) {
284 return null;
285 }
286
287 HRegionInterface newConnection = getCachedConnection(newLocation);
288 if (verifyRegionLocation(newConnection, this.metaLocation, META_REGION)) {
289 setMetaLocation(newLocation);
290 return newConnection;
291 }
292 return null;
293 }
294 }
295
296
297
298
299
300
301 public void waitForMeta() throws InterruptedException {
302 synchronized (metaAvailable) {
303 while (!stopped && !metaAvailable.get()) {
304 metaAvailable.wait();
305 }
306 }
307 }
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322 public HServerAddress waitForMeta(long timeout)
323 throws InterruptedException, IOException, NotAllMetaRegionsOnlineException {
324 long stop = System.currentTimeMillis() + timeout;
325 synchronized (metaAvailable) {
326 while(!stopped && !metaAvailable.get() &&
327 (timeout == 0 || System.currentTimeMillis() < stop)) {
328 if (getMetaServerConnection(true) != null) {
329 return metaLocation;
330 }
331 metaAvailable.wait(timeout == 0 ? 50 : timeout);
332 }
333 if (getMetaServerConnection(true) == null) {
334 throw new NotAllMetaRegionsOnlineException(
335 "Timed out (" + timeout + "ms)");
336 }
337 return metaLocation;
338 }
339 }
340
341
342
343
344
345
346
347
348
349
350 public HRegionInterface waitForMetaServerConnection(long timeout)
351 throws InterruptedException, NotAllMetaRegionsOnlineException, IOException {
352 return getCachedConnection(waitForMeta(timeout));
353 }
354
355
356
357
358
359
360
361
362
363 public HRegionInterface waitForMetaServerConnectionDefault()
364 throws NotAllMetaRegionsOnlineException, IOException {
365 try {
366 return getCachedConnection(waitForMeta(defaultTimeout));
367 } catch (InterruptedException e) {
368 throw new NotAllMetaRegionsOnlineException("Interrupted");
369 }
370 }
371
372 private void resetMetaLocation() {
373 LOG.info("Current cached META location is not valid, resetting");
374 this.metaAvailable.set(false);
375 }
376
377 private void setMetaLocation(HServerAddress metaLocation) {
378 metaAvailable.set(true);
379 this.metaLocation = metaLocation;
380
381 metaAvailable.notifyAll();
382 }
383
384 private HRegionInterface getCachedConnection(HServerAddress address)
385 throws IOException {
386 HRegionInterface protocol = null;
387 try {
388 protocol = connection.getHRegionConnection(address, false);
389 } catch (RetriesExhaustedException e) {
390 if (e.getCause() != null && e.getCause() instanceof ConnectException) {
391
392 } else {
393 throw e;
394 }
395 } catch (SocketTimeoutException e) {
396 LOG.debug("Timed out connecting to " + address);
397 } catch (NoRouteToHostException e) {
398 LOG.debug("Connecting to " + address, e);
399 } catch (SocketException e) {
400 LOG.debug("Exception connecting to " + address);
401 } catch (IOException ioe) {
402 Throwable cause = ioe.getCause();
403 if (cause != null && cause instanceof EOFException) {
404
405 } else if (cause != null && cause.getMessage() != null &&
406 cause.getMessage().toLowerCase().contains("connection reset")) {
407
408 } else {
409 throw ioe;
410 }
411
412 }
413 return protocol;
414 }
415
416 private boolean verifyRegionLocation(HRegionInterface metaServer,
417 final HServerAddress address,
418 byte [] regionName)
419 throws IOException {
420 if (metaServer == null) {
421 LOG.info("Passed metaserver is null");
422 return false;
423 }
424 Throwable t = null;
425 try {
426 return metaServer.getRegionInfo(regionName) != null;
427 } catch (ConnectException e) {
428 t = e;
429 } catch (RemoteException e) {
430 IOException ioe = e.unwrapRemoteException();
431 if (ioe instanceof NotServingRegionException) {
432 t = ioe;
433 } else {
434 throw e;
435 }
436 } catch (IOException e) {
437 Throwable cause = e.getCause();
438 if (cause != null && cause instanceof EOFException) {
439 t = cause;
440 } else if (cause != null && cause.getMessage() != null
441 && cause.getMessage().contains("Connection reset")) {
442 t = cause;
443 } else {
444 throw e;
445 }
446 }
447 LOG.info("Failed verification of " + Bytes.toStringBinary(regionName) +
448 " at address=" + address + "; " + t);
449 return false;
450 }
451
452
453
454
455
456
457
458
459
460 public boolean verifyRootRegionLocation(final long timeout)
461 throws InterruptedException, IOException {
462 HRegionInterface connection = null;
463 try {
464 connection = waitForRootServerConnection(timeout);
465 } catch (NotAllMetaRegionsOnlineException e) {
466
467 } catch (org.apache.hadoop.hbase.ipc.ServerNotRunningException e) {
468
469 } catch (IOException e) {
470
471 throw e;
472 }
473 return (connection == null)? false:
474 verifyRegionLocation(connection,this.rootRegionTracker.getRootRegionLocation(),
475 HRegionInfo.ROOT_REGIONINFO.getRegionName());
476 }
477
478
479
480
481
482
483
484
485
486 public boolean verifyMetaRegionLocation(final long timeout)
487 throws InterruptedException, IOException {
488 return getMetaServerConnection(true) != null;
489 }
490
491 MetaNodeTracker getMetaNodeTracker() {
492 return this.metaNodeTracker;
493 }
494
495 public HConnection getConnection() {
496 return this.connection;
497 }
498 }