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