View Javadoc

1   /**
2    * Copyright 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 java.io.IOException;
23  import java.util.HashSet;
24  import java.util.List;
25  import java.util.Set;
26  
27  import org.apache.hadoop.hbase.TableNotFoundException;
28  import org.apache.hadoop.hbase.TableName;
29  import org.apache.hadoop.hbase.classification.InterfaceAudience;
30  import org.apache.hadoop.hbase.exceptions.DeserializationException;
31  import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
32  import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos;
33  import org.apache.zookeeper.KeeperException;
34  
35  /**
36   * Non-instantiable class that provides helper functions to learn
37   * about HBase table state for code running on client side (hence, not having
38   * access to consensus context).
39   *
40   * Doesn't cache any table state, just goes directly to ZooKeeper.
41   * TODO: decouple this class from ZooKeeper.
42   */
43  @InterfaceAudience.Private
44  public final class ZKTableStateClientSideReader {
45  
46    private ZKTableStateClientSideReader() {}
47    
48    /**
49     * Go to zookeeper and see if state of table is {@code ZooKeeperProtos.Table.State#DISABLED}.
50     * This method does not use cache.
51     * This method is for clients other than AssignmentManager
52     * @param zkw ZooKeeperWatcher instance to use
53     * @param tableName table we're checking
54     * @return True if table is enabled.
55     */
56    public static boolean isDisabledTable(final ZooKeeperWatcher zkw,
57        final TableName tableName)
58        throws KeeperException, InterruptedException, TableNotFoundException {
59      ZooKeeperProtos.Table.State state = getTableState(zkw, tableName);
60      return isTableState(ZooKeeperProtos.Table.State.DISABLED, state);
61    }
62  
63    /**
64     * Go to zookeeper and see if state of table is {@code ZooKeeperProtos.Table.State#ENABLED}.
65     * This method does not use cache.
66     * This method is for clients other than AssignmentManager
67     * @param zkw ZooKeeperWatcher instance to use
68     * @param tableName table we're checking
69     * @return True if table is enabled.
70     * @throws KeeperException
71     */
72    public static boolean isEnabledTable(final ZooKeeperWatcher zkw,
73        final TableName tableName)
74        throws KeeperException, InterruptedException, TableNotFoundException {
75      return getTableState(zkw, tableName) == ZooKeeperProtos.Table.State.ENABLED;
76    }
77  
78    /**
79     * Go to zookeeper and see if state of table is {@code ZooKeeperProtos.Table.State#DISABLING}
80     * of {@code ZooKeeperProtos.Table.State#DISABLED}.
81     * This method does not use cache.
82     * This method is for clients other than AssignmentManager.
83     * @param zkw ZooKeeperWatcher instance to use
84     * @param tableName table we're checking
85     * @return True if table is enabled.
86     * @throws KeeperException
87     */
88    public static boolean isDisablingOrDisabledTable(final ZooKeeperWatcher zkw,
89        final TableName tableName)
90        throws KeeperException, InterruptedException, TableNotFoundException {
91      ZooKeeperProtos.Table.State state = getTableState(zkw, tableName);
92      return isTableState(ZooKeeperProtos.Table.State.DISABLING, state) ||
93        isTableState(ZooKeeperProtos.Table.State.DISABLED, state);
94    }
95  
96    /**
97     * Gets a list of all the tables set as disabled in zookeeper.
98     * @return Set of disabled tables, empty Set if none
99     * @throws KeeperException
100    */
101   public static Set<TableName> getDisabledTables(ZooKeeperWatcher zkw)
102       throws KeeperException, InterruptedException, TableNotFoundException {
103     Set<TableName> disabledTables = new HashSet<TableName>();
104     List<String> children =
105       ZKUtil.listChildrenNoWatch(zkw, zkw.tableZNode);
106     for (String child: children) {
107       TableName tableName =
108           TableName.valueOf(child);
109       ZooKeeperProtos.Table.State state = getTableState(zkw, tableName);
110       if (state == ZooKeeperProtos.Table.State.DISABLED) disabledTables.add(tableName);
111     }
112     return disabledTables;
113   }
114 
115   /**
116    * Gets a list of all the tables set as disabled in zookeeper.
117    * @return Set of disabled tables, empty Set if none
118    * @throws KeeperException
119    */
120   public static Set<TableName> getDisabledOrDisablingTables(ZooKeeperWatcher zkw)
121       throws KeeperException, InterruptedException, TableNotFoundException {
122     return
123         getTablesInStates(
124           zkw,
125           ZooKeeperProtos.Table.State.DISABLED,
126           ZooKeeperProtos.Table.State.DISABLING);
127   }
128 
129   /**
130    * Gets a list of all the tables set as enabling in zookeeper.
131    * @param zkw ZooKeeperWatcher instance to use
132    * @return Set of enabling tables, empty Set if none
133    * @throws KeeperException
134    * @throws InterruptedException
135    */
136   public static Set<TableName> getEnablingTables(ZooKeeperWatcher zkw)
137       throws KeeperException, InterruptedException, TableNotFoundException {
138     return getTablesInStates(zkw, ZooKeeperProtos.Table.State.ENABLING);
139   }
140 
141   /**
142    * Gets a list of tables that are set as one of the passing in states in zookeeper.
143    * @param zkw ZooKeeperWatcher instance to use
144    * @param states the list of states that a table could be in
145    * @return Set of tables in one of the states, empty Set if none
146    * @throws KeeperException
147    * @throws InterruptedException
148    */
149   private static Set<TableName> getTablesInStates(
150     ZooKeeperWatcher zkw,
151     ZooKeeperProtos.Table.State... states)
152       throws KeeperException, InterruptedException, TableNotFoundException {
153     Set<TableName> tableNameSet = new HashSet<TableName>();
154     List<String> children = ZKUtil.listChildrenNoWatch(zkw, zkw.tableZNode);
155     TableName tableName;
156     ZooKeeperProtos.Table.State tableState;
157     for (String child: children) {
158       tableName = TableName.valueOf(child);
159       tableState = getTableState(zkw, tableName);
160       for (ZooKeeperProtos.Table.State state : states) {
161         if (tableState == state) {
162           tableNameSet.add(tableName);
163           break;
164         }
165       }
166     }
167     return tableNameSet;
168   }
169 
170   static boolean isTableState(final ZooKeeperProtos.Table.State expectedState,
171       final ZooKeeperProtos.Table.State currentState) {
172     return currentState != null && currentState.equals(expectedState);
173   }
174 
175   /**
176    * @param zkw ZooKeeperWatcher instance to use
177    * @param tableName table we're checking
178    * @return {@link ZooKeeperProtos.Table.State} found in znode.
179    * @throws KeeperException
180    * @throws TableNotFoundException if tableName doesn't exist
181    */
182   static ZooKeeperProtos.Table.State getTableState(final ZooKeeperWatcher zkw,
183       final TableName tableName)
184       throws KeeperException, InterruptedException, TableNotFoundException {
185     String znode = ZKUtil.joinZNode(zkw.tableZNode, tableName.getNameAsString());
186     byte [] data = ZKUtil.getData(zkw, znode);
187     if (data == null || data.length <= 0) {
188       throw new TableNotFoundException(tableName);
189     }
190     try {
191       ProtobufUtil.expectPBMagicPrefix(data);
192       ZooKeeperProtos.Table.Builder builder = ZooKeeperProtos.Table.newBuilder();
193       int magicLen = ProtobufUtil.lengthOfPBMagic();
194       ProtobufUtil.mergeFrom(builder, data, magicLen, data.length - magicLen);
195       return builder.getState();
196     } catch (IOException e) {
197       KeeperException ke = new KeeperException.DataInconsistencyException();
198       ke.initCause(e);
199       throw ke;
200     } catch (DeserializationException e) {
201       throw ZKUtil.convert(e);
202     }
203   }
204 }