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