View Javadoc

1   /**
2    * Copyright 2010 The Apache Software Foundation
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  package org.apache.hadoop.hbase.zookeeper;
21  
22  import org.apache.hadoop.hbase.Abortable;
23  import org.apache.hadoop.hbase.ServerName;
24  import org.apache.hadoop.hbase.catalog.RootLocationEditor;
25  import org.apache.hadoop.hbase.util.Addressing;
26  import org.apache.hadoop.hbase.util.Bytes;
27  import org.apache.zookeeper.KeeperException;
28  
29  /**
30   * Tracks the root region server location node in zookeeper.
31   * Root region location is set by {@link RootLocationEditor} usually called
32   * out of <code>RegionServerServices</code>.
33   * This class has a watcher on the root location and notices changes.
34   */
35  public class RootRegionTracker extends ZooKeeperNodeTracker {
36    /**
37     * Creates a root region location tracker.
38     *
39     * <p>After construction, use {@link #start} to kick off tracking.
40     *
41     * @param watcher
42     * @param abortable
43     */
44    public RootRegionTracker(ZooKeeperWatcher watcher, Abortable abortable) {
45      super(watcher, watcher.rootServerZNode, abortable);
46    }
47  
48    /**
49     * Checks if the root region location is available.
50     * @return true if root region location is available, false if not
51     */
52    public boolean isLocationAvailable() {
53      return super.getData(true) != null;
54    }
55  
56    /**
57     * Gets the root region location, if available.  Null if not.  Does not block.
58     * @return server name
59     * @throws InterruptedException
60     */
61    public ServerName getRootRegionLocation() throws InterruptedException {
62      return dataToServerName(super.getData(true));
63    }
64  
65    /**
66     * Gets the root region location, if available, and waits for up to the
67     * specified timeout if not immediately available.
68     * Given the zookeeper notification could be delayed, we will try to
69     * get the latest data.
70     * @param timeout maximum time to wait, in millis
71     * @return server name for server hosting root region formatted as per
72     * {@link ServerName}, or null if none available
73     * @throws InterruptedException if interrupted while waiting
74     */
75    public ServerName waitRootRegionLocation(long timeout)
76    throws InterruptedException {
77      if (false == checkIfBaseNodeAvailable()) {
78        String errorMsg = "Check the value configured in 'zookeeper.znode.parent'. "
79            + "There could be a mismatch with the one configured in the master.";
80        LOG.error(errorMsg);
81        throw new IllegalArgumentException(errorMsg);
82      }
83      return dataToServerName(super.blockUntilAvailable(timeout, true));
84    }
85  
86    /*
87     * @param data
88     * @return Returns null if <code>data</code> is null else converts passed data
89     * to a ServerName instance.
90     */
91    private static ServerName dataToServerName(final byte [] data) {
92      // The str returned could be old style -- pre hbase-1502 -- which was
93      // hostname and port seperated by a colon rather than hostname, port and
94      // startcode delimited by a ','.
95      if (data == null || data.length <= 0) return null;
96      String str = Bytes.toString(data);
97      int index = str.indexOf(ServerName.SERVERNAME_SEPARATOR);
98      if (index != -1) {
99        // Presume its ServerName.toString() format.
100       return ServerName.parseServerName(str);
101     }
102     // Presume it a hostname:port format.
103     String hostname = Addressing.parseHostname(str);
104     int port = Addressing.parsePort(str);
105     return new ServerName(hostname, port, -1L);
106   }
107 }