diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/CoordinatedStateManager.java hbase-client/src/main/java/org/apache/hadoop/hbase/CoordinatedStateManager.java deleted file mode 100644 index 2642e29..0000000 --- hbase-client/src/main/java/org/apache/hadoop/hbase/CoordinatedStateManager.java +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hbase; - -import org.apache.hadoop.classification.InterfaceAudience; - -/** - * Implementations of this interface will keep and return to clients - * implementations of classes providing API to execute - * coordinated operations. This interface is client-side, so it does NOT - * include methods to retrieve the particular interface implementations. - * - * For each coarse-grained area of operations there will be a separate - * interface with implementation, providing API for relevant operations - * requiring coordination. - * - * Property hbase.coordinated.state.manager.class in hbase-site.xml controls - * which provider to use. - */ -@InterfaceAudience.Private -public interface CoordinatedStateManager { - - /** - * Initialize coordinated state management service. - * @param server server instance to run within. - */ - void initialize(Server server); - - /** - * Starts service. - */ - void start(); - - /** - * Stops service. - */ - void stop(); - - /** - * @return instance of Server coordinated state manager runs within - */ - Server getServer(); - - /** - * Returns implementation of TableStateManager. - * @throws InterruptedException if operation is interrupted - * @throws CoordinatedStateException if error happens in underlying coordination mechanism - */ - TableStateManager getTableStateManager() throws InterruptedException, - CoordinatedStateException; -} diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/Server.java hbase-client/src/main/java/org/apache/hadoop/hbase/Server.java deleted file mode 100644 index 8f1a004..0000000 --- hbase-client/src/main/java/org/apache/hadoop/hbase/Server.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hbase; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.conf.Configuration; -import org.apache.hadoop.hbase.client.HConnection; -import org.apache.hadoop.hbase.zookeeper.MetaTableLocator; -import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; - -/** - * Defines the set of shared functions implemented by HBase servers (Masters - * and RegionServers). - */ -@InterfaceAudience.Private -public interface Server extends Abortable, Stoppable { - /** - * Gets the configuration object for this server. - */ - Configuration getConfiguration(); - - /** - * Gets the ZooKeeper instance for this server. - */ - ZooKeeperWatcher getZooKeeper(); - - /** - * Returns reference to wrapped short-circuit (i.e. local, bypassing RPC layer entirely) - * HConnection to this server, which may be used for miscellaneous needs. - * - * Important note: this method returns reference to connection which is managed - * by Server itself, so callers must NOT attempt to close connection obtained. - * - * See {@link org.apache.hadoop.hbase.client.ConnectionUtils#createShortCircuitHConnection} - * for details on short-circuit connections. - */ - HConnection getShortCircuitConnection(); - - /** - * Returns instance of {@link org.apache.hadoop.hbase.zookeeper.MetaTableLocator} - * running inside this server. This MetaServerLocator is started and stopped by server, clients - * shouldn't manage it's lifecycle. - * @return instance of {@link MetaTableLocator} associated with this server. - */ - MetaTableLocator getMetaTableLocator(); - - /** - * @return The unique server name for this server. - */ - ServerName getServerName(); - - /** - * Get CoordinatedStateManager instance for this server. - */ - CoordinatedStateManager getCoordinatedStateManager(); -} diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/TableStateManager.java hbase-client/src/main/java/org/apache/hadoop/hbase/TableStateManager.java deleted file mode 100644 index 56cd4ae..0000000 --- hbase-client/src/main/java/org/apache/hadoop/hbase/TableStateManager.java +++ /dev/null @@ -1,115 +0,0 @@ -/** - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hbase; - -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos; - -import java.io.InterruptedIOException; -import java.util.Set; - -/** - * Helper class for table state management for operations running inside - * RegionServer or HMaster. - * Depending on implementation, fetches information from HBase system table, - * local data store, ZooKeeper ensemble or somewhere else. - * Code running on client side (with no coordinated state context) shall instead use - * {@link org.apache.hadoop.hbase.zookeeper.ZKTableStateClientSideReader} - */ -@InterfaceAudience.Private -public interface TableStateManager { - - /** - * Sets the table into desired state. Fails silently if the table is already in this state. - * @param tableName table to process - * @param state new state of this table - * @throws CoordinatedStateException if error happened when trying to set table state - */ - void setTableState(TableName tableName, ZooKeeperProtos.Table.State state) - throws CoordinatedStateException; - - /** - * Sets the specified table into the newState, but only if the table is already in - * one of the possibleCurrentStates (otherwise no operation is performed). - * @param tableName table to process - * @param newState new state for the table - * @param states table should be in one of these states for the operation - * to be performed - * @throws CoordinatedStateException if error happened while performing operation - * @return true if operation succeeded, false otherwise - */ - boolean setTableStateIfInStates(TableName tableName, ZooKeeperProtos.Table.State newState, - ZooKeeperProtos.Table.State... states) - throws CoordinatedStateException; - - /** - * Sets the specified table into the newState, but only if the table is NOT in - * one of the possibleCurrentStates (otherwise no operation is performed). - * @param tableName table to process - * @param newState new state for the table - * @param states table should NOT be in one of these states for the operation - * to be performed - * @throws CoordinatedStateException if error happened while performing operation - * @return true if operation succeeded, false otherwise - */ - boolean setTableStateIfNotInStates(TableName tableName, ZooKeeperProtos.Table.State newState, - ZooKeeperProtos.Table.State... states) - throws CoordinatedStateException; - - /** - * @return true if the table is in any one of the listed states, false otherwise. - */ - boolean isTableState(TableName tableName, ZooKeeperProtos.Table.State... states); - - /** - * Mark table as deleted. Fails silently if the table is not currently marked as disabled. - * @param tableName table to be deleted - * @throws CoordinatedStateException if error happened while performing operation - */ - void setDeletedTable(TableName tableName) throws CoordinatedStateException; - - /** - * Checks if table is present. - * - * @param tableName table we're checking - * @return true if the table is present, false otherwise - */ - boolean isTablePresent(TableName tableName); - - /** - * @return set of tables which are in any one of the listed states, empty Set if none - */ - Set getTablesInStates(ZooKeeperProtos.Table.State... states) - throws InterruptedIOException, CoordinatedStateException; - - /** - * If the table is found in the given state the in-memory state is removed. This - * helps in cases where CreateTable is to be retried by the client in case of - * failures. If deletePermanentState is true - the flag kept permanently is - * also reset. - * - * @param tableName table we're working on - * @param states if table isn't in any one of these states, operation aborts - * @param deletePermanentState if true, reset the permanent flag - * @throws CoordinatedStateException if error happened in underlying coordination engine - */ - void checkAndRemoveTableState(TableName tableName, ZooKeeperProtos.Table.State states, - boolean deletePermanentState) - throws CoordinatedStateException; -} diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTableStateManager.java hbase-client/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTableStateManager.java deleted file mode 100644 index 1aff12f..0000000 --- hbase-client/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTableStateManager.java +++ /dev/null @@ -1,330 +0,0 @@ -/** - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.apache.hadoop.hbase.zookeeper; - -import com.google.protobuf.InvalidProtocolBufferException; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.classification.InterfaceAudience; -import org.apache.hadoop.hbase.CoordinatedStateException; -import org.apache.hadoop.hbase.TableName; -import org.apache.hadoop.hbase.TableStateManager; -import org.apache.hadoop.hbase.exceptions.DeserializationException; -import org.apache.hadoop.hbase.protobuf.ProtobufUtil; -import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos; -import org.apache.zookeeper.KeeperException; - -import java.io.InterruptedIOException; -import java.util.Arrays; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -/** - * Implementation of TableStateManager which reads, caches and sets state - * up in ZooKeeper. If multiple read/write clients, will make for confusion. - * Code running on client side without consensus context should use - * {@link ZKTableStateClientSideReader} instead. - * - *

To save on trips to the zookeeper ensemble, internally we cache table - * state. - */ -@InterfaceAudience.Private -public class ZKTableStateManager implements TableStateManager { - // A znode will exist under the table directory if it is in any of the - // following states: {@link TableState#ENABLING} , {@link TableState#DISABLING}, - // or {@link TableState#DISABLED}. If {@link TableState#ENABLED}, there will - // be no entry for a table in zk. Thats how it currently works. - - private static final Log LOG = LogFactory.getLog(ZKTableStateManager.class); - private final ZooKeeperWatcher watcher; - - /** - * Cache of what we found in zookeeper so we don't have to go to zk ensemble - * for every query. Synchronize access rather than use concurrent Map because - * synchronization needs to span query of zk. - */ - private final Map cache = - new HashMap(); - - public ZKTableStateManager(final ZooKeeperWatcher zkw) throws KeeperException, - InterruptedException { - super(); - this.watcher = zkw; - populateTableStates(); - } - - /** - * Gets a list of all the tables set as disabled in zookeeper. - * @throws KeeperException, InterruptedException - */ - private void populateTableStates() throws KeeperException, InterruptedException { - synchronized (this.cache) { - List children = ZKUtil.listChildrenNoWatch(this.watcher, this.watcher.tableZNode); - if (children == null) return; - for (String child: children) { - TableName tableName = TableName.valueOf(child); - ZooKeeperProtos.Table.State state = getTableState(this.watcher, tableName); - if (state != null) this.cache.put(tableName, state); - } - } - } - - /** - * Sets table state in ZK. Sets no watches. - * - * {@inheritDoc} - */ - @Override - public void setTableState(TableName tableName, ZooKeeperProtos.Table.State state) - throws CoordinatedStateException { - synchronized (this.cache) { - LOG.warn("Moving table " + tableName + " state from " + this.cache.get(tableName) - + " to " + state); - try { - setTableStateInZK(tableName, state); - } catch (KeeperException e) { - throw new CoordinatedStateException(e); - } - } - } - - /** - * Checks and sets table state in ZK. Sets no watches. - * {@inheritDoc} - */ - @Override - public boolean setTableStateIfInStates(TableName tableName, - ZooKeeperProtos.Table.State newState, - ZooKeeperProtos.Table.State... states) - throws CoordinatedStateException { - synchronized (this.cache) { - // Transition ENABLED->DISABLING has to be performed with a hack, because - // we treat empty state as enabled in this case because 0.92- clusters. - if ( - (newState == ZooKeeperProtos.Table.State.DISABLING) && - this.cache.get(tableName) != null && !isTableState(tableName, states) || - (newState != ZooKeeperProtos.Table.State.DISABLING && - !isTableState(tableName, states) )) { - return false; - } - try { - setTableStateInZK(tableName, newState); - } catch (KeeperException e) { - throw new CoordinatedStateException(e); - } - return true; - } - } - - /** - * Checks and sets table state in ZK. Sets no watches. - * {@inheritDoc} - */ - @Override - public boolean setTableStateIfNotInStates(TableName tableName, - ZooKeeperProtos.Table.State newState, - ZooKeeperProtos.Table.State... states) - throws CoordinatedStateException { - synchronized (this.cache) { - if (isTableState(tableName, states)) { - return false; - } - try { - setTableStateInZK(tableName, newState); - } catch (KeeperException e) { - throw new CoordinatedStateException(e); - } - return true; - } - } - - private void setTableStateInZK(final TableName tableName, - final ZooKeeperProtos.Table.State state) - throws KeeperException { - String znode = ZKUtil.joinZNode(this.watcher.tableZNode, tableName.getNameAsString()); - if (ZKUtil.checkExists(this.watcher, znode) == -1) { - ZKUtil.createAndFailSilent(this.watcher, znode); - } - synchronized (this.cache) { - ZooKeeperProtos.Table.Builder builder = ZooKeeperProtos.Table.newBuilder(); - builder.setState(state); - byte [] data = ProtobufUtil.prependPBMagic(builder.build().toByteArray()); - ZKUtil.setData(this.watcher, znode, data); - this.cache.put(tableName, state); - } - } - - /** - * Checks if table is marked in specified state in ZK. - * - * {@inheritDoc} - */ - @Override - public boolean isTableState(final TableName tableName, - final ZooKeeperProtos.Table.State... states) { - synchronized (this.cache) { - ZooKeeperProtos.Table.State currentState = this.cache.get(tableName); - return isTableInState(Arrays.asList(states), currentState); - } - } - - /** - * Deletes the table in zookeeper. Fails silently if the - * table is not currently disabled in zookeeper. Sets no watches. - * - * {@inheritDoc} - */ - @Override - public void setDeletedTable(final TableName tableName) - throws CoordinatedStateException { - synchronized (this.cache) { - if (this.cache.remove(tableName) == null) { - LOG.warn("Moving table " + tableName + " state to deleted but was " + - "already deleted"); - } - try { - ZKUtil.deleteNodeFailSilent(this.watcher, - ZKUtil.joinZNode(this.watcher.tableZNode, tableName.getNameAsString())); - } catch (KeeperException e) { - throw new CoordinatedStateException(e); - } - } - } - - /** - * check if table is present. - * - * @param tableName table we're working on - * @return true if the table is present - */ - @Override - public boolean isTablePresent(final TableName tableName) { - synchronized (this.cache) { - ZooKeeperProtos.Table.State state = this.cache.get(tableName); - return !(state == null); - } - } - - /** - * Gets a list of all the tables set as disabling in zookeeper. - * @return Set of disabling tables, empty Set if none - * @throws CoordinatedStateException if error happened in underlying coordination engine - */ - @Override - public Set getTablesInStates(ZooKeeperProtos.Table.State... states) - throws InterruptedIOException, CoordinatedStateException { - try { - return getAllTables(states); - } catch (KeeperException e) { - throw new CoordinatedStateException(e); - } - } - - /** - * {@inheritDoc} - */ - @Override - public void checkAndRemoveTableState(TableName tableName, ZooKeeperProtos.Table.State states, - boolean deletePermanentState) - throws CoordinatedStateException { - synchronized (this.cache) { - if (isTableState(tableName, states)) { - this.cache.remove(tableName); - if (deletePermanentState) { - try { - ZKUtil.deleteNodeFailSilent(this.watcher, - ZKUtil.joinZNode(this.watcher.tableZNode, tableName.getNameAsString())); - } catch (KeeperException e) { - throw new CoordinatedStateException(e); - } - } - } - } - } - - /** - * Gets a list of all the tables of specified states in zookeeper. - * @return Set of tables of specified states, empty Set if none - * @throws KeeperException - */ - Set getAllTables(final ZooKeeperProtos.Table.State... states) - throws KeeperException, InterruptedIOException { - - Set allTables = new HashSet(); - List children = - ZKUtil.listChildrenNoWatch(watcher, watcher.tableZNode); - if(children == null) return allTables; - for (String child: children) { - TableName tableName = TableName.valueOf(child); - ZooKeeperProtos.Table.State state; - try { - state = getTableState(watcher, tableName); - } catch (InterruptedException e) { - throw new InterruptedIOException(); - } - for (ZooKeeperProtos.Table.State expectedState: states) { - if (state == expectedState) { - allTables.add(tableName); - break; - } - } - } - return allTables; - } - - /** - * Gets table state from ZK. - * @param zkw ZooKeeperWatcher instance to use - * @param tableName table we're checking - * @return Null or {@link ZooKeeperProtos.Table.State} found in znode. - * @throws KeeperException - */ - private ZooKeeperProtos.Table.State getTableState(final ZooKeeperWatcher zkw, - final TableName tableName) - throws KeeperException, InterruptedException { - String znode = ZKUtil.joinZNode(zkw.tableZNode, tableName.getNameAsString()); - byte [] data = ZKUtil.getData(zkw, znode); - if (data == null || data.length <= 0) return null; - try { - ProtobufUtil.expectPBMagicPrefix(data); - ZooKeeperProtos.Table.Builder builder = ZooKeeperProtos.Table.newBuilder(); - int magicLen = ProtobufUtil.lengthOfPBMagic(); - ZooKeeperProtos.Table t = builder.mergeFrom(data, magicLen, data.length - magicLen).build(); - return t.getState(); - } catch (InvalidProtocolBufferException e) { - KeeperException ke = new KeeperException.DataInconsistencyException(); - ke.initCause(e); - throw ke; - } catch (DeserializationException e) { - throw ZKUtil.convert(e); - } - } - - /** - * @return true if current state isn't null and is contained - * in the list of expected states. - */ - private boolean isTableInState(final List expectedStates, - final ZooKeeperProtos.Table.State currentState) { - return currentState != null && expectedStates.contains(currentState); - } -} diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/CoordinatedStateManager.java hbase-server/src/main/java/org/apache/hadoop/hbase/CoordinatedStateManager.java new file mode 100644 index 0000000..2642e29 --- /dev/null +++ hbase-server/src/main/java/org/apache/hadoop/hbase/CoordinatedStateManager.java @@ -0,0 +1,66 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase; + +import org.apache.hadoop.classification.InterfaceAudience; + +/** + * Implementations of this interface will keep and return to clients + * implementations of classes providing API to execute + * coordinated operations. This interface is client-side, so it does NOT + * include methods to retrieve the particular interface implementations. + * + * For each coarse-grained area of operations there will be a separate + * interface with implementation, providing API for relevant operations + * requiring coordination. + * + * Property hbase.coordinated.state.manager.class in hbase-site.xml controls + * which provider to use. + */ +@InterfaceAudience.Private +public interface CoordinatedStateManager { + + /** + * Initialize coordinated state management service. + * @param server server instance to run within. + */ + void initialize(Server server); + + /** + * Starts service. + */ + void start(); + + /** + * Stops service. + */ + void stop(); + + /** + * @return instance of Server coordinated state manager runs within + */ + Server getServer(); + + /** + * Returns implementation of TableStateManager. + * @throws InterruptedException if operation is interrupted + * @throws CoordinatedStateException if error happens in underlying coordination mechanism + */ + TableStateManager getTableStateManager() throws InterruptedException, + CoordinatedStateException; +} diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/Server.java hbase-server/src/main/java/org/apache/hadoop/hbase/Server.java new file mode 100644 index 0000000..8f1a004 --- /dev/null +++ hbase-server/src/main/java/org/apache/hadoop/hbase/Server.java @@ -0,0 +1,72 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase; + +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.client.HConnection; +import org.apache.hadoop.hbase.zookeeper.MetaTableLocator; +import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher; + +/** + * Defines the set of shared functions implemented by HBase servers (Masters + * and RegionServers). + */ +@InterfaceAudience.Private +public interface Server extends Abortable, Stoppable { + /** + * Gets the configuration object for this server. + */ + Configuration getConfiguration(); + + /** + * Gets the ZooKeeper instance for this server. + */ + ZooKeeperWatcher getZooKeeper(); + + /** + * Returns reference to wrapped short-circuit (i.e. local, bypassing RPC layer entirely) + * HConnection to this server, which may be used for miscellaneous needs. + * + * Important note: this method returns reference to connection which is managed + * by Server itself, so callers must NOT attempt to close connection obtained. + * + * See {@link org.apache.hadoop.hbase.client.ConnectionUtils#createShortCircuitHConnection} + * for details on short-circuit connections. + */ + HConnection getShortCircuitConnection(); + + /** + * Returns instance of {@link org.apache.hadoop.hbase.zookeeper.MetaTableLocator} + * running inside this server. This MetaServerLocator is started and stopped by server, clients + * shouldn't manage it's lifecycle. + * @return instance of {@link MetaTableLocator} associated with this server. + */ + MetaTableLocator getMetaTableLocator(); + + /** + * @return The unique server name for this server. + */ + ServerName getServerName(); + + /** + * Get CoordinatedStateManager instance for this server. + */ + CoordinatedStateManager getCoordinatedStateManager(); +} diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/TableStateManager.java hbase-server/src/main/java/org/apache/hadoop/hbase/TableStateManager.java new file mode 100644 index 0000000..56cd4ae --- /dev/null +++ hbase-server/src/main/java/org/apache/hadoop/hbase/TableStateManager.java @@ -0,0 +1,115 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase; + +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos; + +import java.io.InterruptedIOException; +import java.util.Set; + +/** + * Helper class for table state management for operations running inside + * RegionServer or HMaster. + * Depending on implementation, fetches information from HBase system table, + * local data store, ZooKeeper ensemble or somewhere else. + * Code running on client side (with no coordinated state context) shall instead use + * {@link org.apache.hadoop.hbase.zookeeper.ZKTableStateClientSideReader} + */ +@InterfaceAudience.Private +public interface TableStateManager { + + /** + * Sets the table into desired state. Fails silently if the table is already in this state. + * @param tableName table to process + * @param state new state of this table + * @throws CoordinatedStateException if error happened when trying to set table state + */ + void setTableState(TableName tableName, ZooKeeperProtos.Table.State state) + throws CoordinatedStateException; + + /** + * Sets the specified table into the newState, but only if the table is already in + * one of the possibleCurrentStates (otherwise no operation is performed). + * @param tableName table to process + * @param newState new state for the table + * @param states table should be in one of these states for the operation + * to be performed + * @throws CoordinatedStateException if error happened while performing operation + * @return true if operation succeeded, false otherwise + */ + boolean setTableStateIfInStates(TableName tableName, ZooKeeperProtos.Table.State newState, + ZooKeeperProtos.Table.State... states) + throws CoordinatedStateException; + + /** + * Sets the specified table into the newState, but only if the table is NOT in + * one of the possibleCurrentStates (otherwise no operation is performed). + * @param tableName table to process + * @param newState new state for the table + * @param states table should NOT be in one of these states for the operation + * to be performed + * @throws CoordinatedStateException if error happened while performing operation + * @return true if operation succeeded, false otherwise + */ + boolean setTableStateIfNotInStates(TableName tableName, ZooKeeperProtos.Table.State newState, + ZooKeeperProtos.Table.State... states) + throws CoordinatedStateException; + + /** + * @return true if the table is in any one of the listed states, false otherwise. + */ + boolean isTableState(TableName tableName, ZooKeeperProtos.Table.State... states); + + /** + * Mark table as deleted. Fails silently if the table is not currently marked as disabled. + * @param tableName table to be deleted + * @throws CoordinatedStateException if error happened while performing operation + */ + void setDeletedTable(TableName tableName) throws CoordinatedStateException; + + /** + * Checks if table is present. + * + * @param tableName table we're checking + * @return true if the table is present, false otherwise + */ + boolean isTablePresent(TableName tableName); + + /** + * @return set of tables which are in any one of the listed states, empty Set if none + */ + Set getTablesInStates(ZooKeeperProtos.Table.State... states) + throws InterruptedIOException, CoordinatedStateException; + + /** + * If the table is found in the given state the in-memory state is removed. This + * helps in cases where CreateTable is to be retried by the client in case of + * failures. If deletePermanentState is true - the flag kept permanently is + * also reset. + * + * @param tableName table we're working on + * @param states if table isn't in any one of these states, operation aborts + * @param deletePermanentState if true, reset the permanent flag + * @throws CoordinatedStateException if error happened in underlying coordination engine + */ + void checkAndRemoveTableState(TableName tableName, ZooKeeperProtos.Table.State states, + boolean deletePermanentState) + throws CoordinatedStateException; +} diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTableStateManager.java hbase-server/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTableStateManager.java new file mode 100644 index 0000000..1aff12f --- /dev/null +++ hbase-server/src/main/java/org/apache/hadoop/hbase/zookeeper/ZKTableStateManager.java @@ -0,0 +1,330 @@ +/** + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.hadoop.hbase.zookeeper; + +import com.google.protobuf.InvalidProtocolBufferException; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.classification.InterfaceAudience; +import org.apache.hadoop.hbase.CoordinatedStateException; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.TableStateManager; +import org.apache.hadoop.hbase.exceptions.DeserializationException; +import org.apache.hadoop.hbase.protobuf.ProtobufUtil; +import org.apache.hadoop.hbase.protobuf.generated.ZooKeeperProtos; +import org.apache.zookeeper.KeeperException; + +import java.io.InterruptedIOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Implementation of TableStateManager which reads, caches and sets state + * up in ZooKeeper. If multiple read/write clients, will make for confusion. + * Code running on client side without consensus context should use + * {@link ZKTableStateClientSideReader} instead. + * + *

To save on trips to the zookeeper ensemble, internally we cache table + * state. + */ +@InterfaceAudience.Private +public class ZKTableStateManager implements TableStateManager { + // A znode will exist under the table directory if it is in any of the + // following states: {@link TableState#ENABLING} , {@link TableState#DISABLING}, + // or {@link TableState#DISABLED}. If {@link TableState#ENABLED}, there will + // be no entry for a table in zk. Thats how it currently works. + + private static final Log LOG = LogFactory.getLog(ZKTableStateManager.class); + private final ZooKeeperWatcher watcher; + + /** + * Cache of what we found in zookeeper so we don't have to go to zk ensemble + * for every query. Synchronize access rather than use concurrent Map because + * synchronization needs to span query of zk. + */ + private final Map cache = + new HashMap(); + + public ZKTableStateManager(final ZooKeeperWatcher zkw) throws KeeperException, + InterruptedException { + super(); + this.watcher = zkw; + populateTableStates(); + } + + /** + * Gets a list of all the tables set as disabled in zookeeper. + * @throws KeeperException, InterruptedException + */ + private void populateTableStates() throws KeeperException, InterruptedException { + synchronized (this.cache) { + List children = ZKUtil.listChildrenNoWatch(this.watcher, this.watcher.tableZNode); + if (children == null) return; + for (String child: children) { + TableName tableName = TableName.valueOf(child); + ZooKeeperProtos.Table.State state = getTableState(this.watcher, tableName); + if (state != null) this.cache.put(tableName, state); + } + } + } + + /** + * Sets table state in ZK. Sets no watches. + * + * {@inheritDoc} + */ + @Override + public void setTableState(TableName tableName, ZooKeeperProtos.Table.State state) + throws CoordinatedStateException { + synchronized (this.cache) { + LOG.warn("Moving table " + tableName + " state from " + this.cache.get(tableName) + + " to " + state); + try { + setTableStateInZK(tableName, state); + } catch (KeeperException e) { + throw new CoordinatedStateException(e); + } + } + } + + /** + * Checks and sets table state in ZK. Sets no watches. + * {@inheritDoc} + */ + @Override + public boolean setTableStateIfInStates(TableName tableName, + ZooKeeperProtos.Table.State newState, + ZooKeeperProtos.Table.State... states) + throws CoordinatedStateException { + synchronized (this.cache) { + // Transition ENABLED->DISABLING has to be performed with a hack, because + // we treat empty state as enabled in this case because 0.92- clusters. + if ( + (newState == ZooKeeperProtos.Table.State.DISABLING) && + this.cache.get(tableName) != null && !isTableState(tableName, states) || + (newState != ZooKeeperProtos.Table.State.DISABLING && + !isTableState(tableName, states) )) { + return false; + } + try { + setTableStateInZK(tableName, newState); + } catch (KeeperException e) { + throw new CoordinatedStateException(e); + } + return true; + } + } + + /** + * Checks and sets table state in ZK. Sets no watches. + * {@inheritDoc} + */ + @Override + public boolean setTableStateIfNotInStates(TableName tableName, + ZooKeeperProtos.Table.State newState, + ZooKeeperProtos.Table.State... states) + throws CoordinatedStateException { + synchronized (this.cache) { + if (isTableState(tableName, states)) { + return false; + } + try { + setTableStateInZK(tableName, newState); + } catch (KeeperException e) { + throw new CoordinatedStateException(e); + } + return true; + } + } + + private void setTableStateInZK(final TableName tableName, + final ZooKeeperProtos.Table.State state) + throws KeeperException { + String znode = ZKUtil.joinZNode(this.watcher.tableZNode, tableName.getNameAsString()); + if (ZKUtil.checkExists(this.watcher, znode) == -1) { + ZKUtil.createAndFailSilent(this.watcher, znode); + } + synchronized (this.cache) { + ZooKeeperProtos.Table.Builder builder = ZooKeeperProtos.Table.newBuilder(); + builder.setState(state); + byte [] data = ProtobufUtil.prependPBMagic(builder.build().toByteArray()); + ZKUtil.setData(this.watcher, znode, data); + this.cache.put(tableName, state); + } + } + + /** + * Checks if table is marked in specified state in ZK. + * + * {@inheritDoc} + */ + @Override + public boolean isTableState(final TableName tableName, + final ZooKeeperProtos.Table.State... states) { + synchronized (this.cache) { + ZooKeeperProtos.Table.State currentState = this.cache.get(tableName); + return isTableInState(Arrays.asList(states), currentState); + } + } + + /** + * Deletes the table in zookeeper. Fails silently if the + * table is not currently disabled in zookeeper. Sets no watches. + * + * {@inheritDoc} + */ + @Override + public void setDeletedTable(final TableName tableName) + throws CoordinatedStateException { + synchronized (this.cache) { + if (this.cache.remove(tableName) == null) { + LOG.warn("Moving table " + tableName + " state to deleted but was " + + "already deleted"); + } + try { + ZKUtil.deleteNodeFailSilent(this.watcher, + ZKUtil.joinZNode(this.watcher.tableZNode, tableName.getNameAsString())); + } catch (KeeperException e) { + throw new CoordinatedStateException(e); + } + } + } + + /** + * check if table is present. + * + * @param tableName table we're working on + * @return true if the table is present + */ + @Override + public boolean isTablePresent(final TableName tableName) { + synchronized (this.cache) { + ZooKeeperProtos.Table.State state = this.cache.get(tableName); + return !(state == null); + } + } + + /** + * Gets a list of all the tables set as disabling in zookeeper. + * @return Set of disabling tables, empty Set if none + * @throws CoordinatedStateException if error happened in underlying coordination engine + */ + @Override + public Set getTablesInStates(ZooKeeperProtos.Table.State... states) + throws InterruptedIOException, CoordinatedStateException { + try { + return getAllTables(states); + } catch (KeeperException e) { + throw new CoordinatedStateException(e); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void checkAndRemoveTableState(TableName tableName, ZooKeeperProtos.Table.State states, + boolean deletePermanentState) + throws CoordinatedStateException { + synchronized (this.cache) { + if (isTableState(tableName, states)) { + this.cache.remove(tableName); + if (deletePermanentState) { + try { + ZKUtil.deleteNodeFailSilent(this.watcher, + ZKUtil.joinZNode(this.watcher.tableZNode, tableName.getNameAsString())); + } catch (KeeperException e) { + throw new CoordinatedStateException(e); + } + } + } + } + } + + /** + * Gets a list of all the tables of specified states in zookeeper. + * @return Set of tables of specified states, empty Set if none + * @throws KeeperException + */ + Set getAllTables(final ZooKeeperProtos.Table.State... states) + throws KeeperException, InterruptedIOException { + + Set allTables = new HashSet(); + List children = + ZKUtil.listChildrenNoWatch(watcher, watcher.tableZNode); + if(children == null) return allTables; + for (String child: children) { + TableName tableName = TableName.valueOf(child); + ZooKeeperProtos.Table.State state; + try { + state = getTableState(watcher, tableName); + } catch (InterruptedException e) { + throw new InterruptedIOException(); + } + for (ZooKeeperProtos.Table.State expectedState: states) { + if (state == expectedState) { + allTables.add(tableName); + break; + } + } + } + return allTables; + } + + /** + * Gets table state from ZK. + * @param zkw ZooKeeperWatcher instance to use + * @param tableName table we're checking + * @return Null or {@link ZooKeeperProtos.Table.State} found in znode. + * @throws KeeperException + */ + private ZooKeeperProtos.Table.State getTableState(final ZooKeeperWatcher zkw, + final TableName tableName) + throws KeeperException, InterruptedException { + String znode = ZKUtil.joinZNode(zkw.tableZNode, tableName.getNameAsString()); + byte [] data = ZKUtil.getData(zkw, znode); + if (data == null || data.length <= 0) return null; + try { + ProtobufUtil.expectPBMagicPrefix(data); + ZooKeeperProtos.Table.Builder builder = ZooKeeperProtos.Table.newBuilder(); + int magicLen = ProtobufUtil.lengthOfPBMagic(); + ZooKeeperProtos.Table t = builder.mergeFrom(data, magicLen, data.length - magicLen).build(); + return t.getState(); + } catch (InvalidProtocolBufferException e) { + KeeperException ke = new KeeperException.DataInconsistencyException(); + ke.initCause(e); + throw ke; + } catch (DeserializationException e) { + throw ZKUtil.convert(e); + } + } + + /** + * @return true if current state isn't null and is contained + * in the list of expected states. + */ + private boolean isTableInState(final List expectedStates, + final ZooKeeperProtos.Table.State currentState) { + return currentState != null && expectedStates.contains(currentState); + } +}