From 94397255d706e1030f63073d0dcd241d0a831808 Mon Sep 17 00:00:00 2001 From: Umesh Agashe Date: Tue, 7 Aug 2018 11:46:42 -0700 Subject: [PATCH] HBASE-20941 Created and implemented HbckService in master Added API setTableStateInMeta() to update table state only in Meta. This will be used by hbck2 tool. --- .../org/apache/hadoop/hbase/client/Connection.java | 14 +++ .../hbase/client/ConnectionImplementation.java | 18 ++++ .../org/apache/hadoop/hbase/client/HBaseHbck.java | 113 +++++++++++++++++++++ .../java/org/apache/hadoop/hbase/client/Hbck.java | 55 ++++++++++ .../hbase/shaded/protobuf/RequestConverter.java | 12 +++ .../hadoop/hbase/HBaseInterfaceAudience.java | 5 + .../mapreduce/TestMultiTableInputFormatBase.java | 6 ++ .../hbase/mapreduce/TestTableInputFormatBase.java | 6 ++ .../src/main/protobuf/Master.proto | 11 ++ .../org/apache/hadoop/hbase/SharedConnection.java | 6 ++ .../hadoop/hbase/master/MasterRpcServices.java | 32 +++++- .../apache/hadoop/hbase/HBaseTestingUtility.java | 13 +++ .../org/apache/hadoop/hbase/client/TestHbck.java | 104 +++++++++++++++++++ .../regionserver/TestWALEntrySinkFilter.java | 6 ++ .../hbase/spark/HBaseConnectionCacheSuite.scala | 3 +- 15 files changed, 402 insertions(+), 2 deletions(-) create mode 100644 hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java create mode 100644 hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java create mode 100644 hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Connection.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Connection.java index 1d28777ee08e5ea2073e5a5338168e7a1ba52c8c..c207031e04ecd19fc58570840191397e5d6cc6ae 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Connection.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Connection.java @@ -167,6 +167,20 @@ public interface Connection extends Abortable, Closeable { */ Admin getAdmin() throws IOException; + /** + * Retrieve an Hbck implementation to fix an HBase cluster. + * The returned Hbck is not guaranteed to be thread-safe. A new instance should be created by + * each thread. This is a lightweight operation. Pooling or caching of the returned Hbck instance + * is not recommended. + *
+ * The caller is responsible for calling {@link Hbck#close()} on the returned Hbck instance. + *
+ * This will be used mostly by hbck tool. + * + * @return an Hbck instance for cluster + */ + Hbck getHbck() throws IOException; + @Override void close() throws IOException; diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java index 7e07dafa7e70b5767cffaf8b9cd4b8ae56d58e32..15bf14cab9d6ed9aa734ff53b28cdac8bc5015ea 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java @@ -422,6 +422,24 @@ class ConnectionImplementation implements ClusterConnection, Closeable { return new HBaseAdmin(this); } + @Override + public Hbck getHbck() throws IOException { + checkClosed(); + ServerName masterServer = get(registry.getMasterAddress()); + if (isDeadServer(masterServer)) { + throw new RegionServerStoppedException(masterServer + " is dead."); + } + String key = getStubKey(MasterProtos.HbckService.BlockingInterface.class.getName(), + masterServer, this.hostnamesCanChange); + + return new HBaseHbck(this, + (MasterProtos.HbckService.BlockingInterface) computeIfAbsentEx(stubs, key, () -> { + BlockingRpcChannel channel = + this.rpcClient.createBlockingRpcChannel(masterServer, user, rpcTimeout); + return MasterProtos.HbckService.newBlockingStub(channel); + })); + } + @Override public MetricsConnection getConnectionMetrics() { return this.metrics; diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java new file mode 100644 index 0000000000000000000000000000000000000000..9bf8fdbf6a4beef8444e2a143d9b14843339b422 --- /dev/null +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseHbck.java @@ -0,0 +1,113 @@ +/* + * 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.client; + +import java.io.IOException; +import java.util.concurrent.Callable; +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.ipc.RpcControllerFactory; +import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; +import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableStateResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.HbckService.BlockingInterface; +import org.apache.yetus.audience.InterfaceAudience; +import org.apache.yetus.audience.InterfaceStability; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * Use {@link Connection#getHbck()} to obtain an instance of {@link Hbck} instead of constructing + * an HBaseHbck directly. This will be mostly used by hbck tool. + * + *

Connection should be an unmanaged connection obtained via + * {@link ConnectionFactory#createConnection(Configuration)}.

+ * + * @see ConnectionFactory + * @see Connection + * @see Hbck + */ +@InterfaceAudience.Private +@InterfaceStability.Evolving +public class HBaseHbck implements Hbck { + private static final Logger LOG = LoggerFactory.getLogger(HBaseHbck.class); + + private ClusterConnection connection; + + private final Configuration conf; + private boolean aborted; + private int operationTimeout; + private final BlockingInterface hbck; + + private RpcControllerFactory rpcControllerFactory; + + HBaseHbck(ClusterConnection connection, BlockingInterface hbck) throws IOException { + this.connection = connection; + this.conf = this.connection.getConfiguration(); + this.hbck = hbck; + this.rpcControllerFactory = this.connection.getRpcControllerFactory(); + + this.operationTimeout = this.conf.getInt(HConstants.HBASE_CLIENT_OPERATION_TIMEOUT, + HConstants.DEFAULT_HBASE_CLIENT_OPERATION_TIMEOUT); + } + + @Override + public int getOperationTimeout() { + return operationTimeout; + } + + @Override + public Connection getConnection() { + return connection; + } + + @Override + public synchronized void close() throws IOException { + // currently does nothing + } + + @Override + public void abort(String why, Throwable e) { + this.aborted = true; + // Currently does nothing but throw the passed message and exception + throw new RuntimeException(why, e); + } + + @Override + public boolean isAborted() { + return this.aborted; + } + + @Override + public TableState setTableStateInMeta(TableState state) throws IOException { + GetTableStateResponse response = ProtobufUtil.call(new Callable() { + @Override + public GetTableStateResponse call() throws Exception { + try { + return hbck.setTableStateInMeta(rpcControllerFactory.newController(), + RequestConverter.buildSetTableStateInMetaRequest(state)); + } catch (Throwable t) { + LOG.error("Error = {}", t); + throw t; + } + } + }); + return TableState.convert(state.getTableName(), response.getTableState()); + } +} diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java new file mode 100644 index 0000000000000000000000000000000000000000..d79a4e5426c45f699519b75d435027dff0e23dda --- /dev/null +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Hbck.java @@ -0,0 +1,55 @@ +/* + * 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.client; + +import java.io.Closeable; +import java.io.IOException; +import org.apache.hadoop.hbase.Abortable; +import org.apache.hadoop.hbase.HBaseInterfaceAudience; +import org.apache.yetus.audience.InterfaceAudience; +import org.apache.yetus.audience.InterfaceStability; + +/** + * Hbck APIs for HBase. Obtain an instance from {@link Connection#getHbck()} and call + * {@link #close()} when done. + *

Hbck can be used by operators to fix HBase and bringging it to consistent state. Mostly used + * by hbck tool.

+ * + * @see ConnectionFactory + * @see Connection + * @since 2.1.0 + */ +@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.HBCK) +@InterfaceStability.Evolving +public interface Hbck extends Abortable, Closeable { + + int getOperationTimeout(); + + /** + * @return Connection used by this object. + */ + Connection getConnection(); + + /** + * Update table state in Meta only. + * + * @param state table state + * @return previous state of the table in Meta + */ + TableState setTableStateInMeta(TableState state) throws IOException; +} diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java index db07bab46f17c2eed05a663aec4762dafd01aa25..41abf97696f51c7b1611e2d76ecb700b4e240f42 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java @@ -50,6 +50,7 @@ import org.apache.hadoop.hbase.client.Row; import org.apache.hadoop.hbase.client.RowMutations; import org.apache.hadoop.hbase.client.Scan; import org.apache.hadoop.hbase.client.TableDescriptor; +import org.apache.hadoop.hbase.client.TableState; import org.apache.hadoop.hbase.client.replication.ReplicationPeerConfigUtil; import org.apache.hadoop.hbase.exceptions.DeserializationException; import org.apache.hadoop.hbase.filter.ByteArrayComparable; @@ -134,6 +135,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetBalance import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetCleanerChoreRunningRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetNormalizerRunningRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetSplitOrMergeEnabledRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetTableStateInMetaRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SplitTableRegionRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.TruncateTableRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.UnassignRegionRequest; @@ -1444,6 +1446,16 @@ public final class RequestConverter { .build(); } + /** + * Creates a protocol buffer SetTableStateInMetaRequest + * @param state table state to update in Meta + * @return a SetTableStateInMetaRequest + */ + public static SetTableStateInMetaRequest buildSetTableStateInMetaRequest(final TableState state) { + return SetTableStateInMetaRequest.newBuilder().setTableState(state.convert()) + .setTableName(ProtobufUtil.toProtoTableName(state.getTableName())).build(); + } + /** * Creates a protocol buffer GetTableDescriptorsRequest for a single table * diff --git a/hbase-common/src/main/java/org/apache/hadoop/hbase/HBaseInterfaceAudience.java b/hbase-common/src/main/java/org/apache/hadoop/hbase/HBaseInterfaceAudience.java index 4e034577b7cb76a49edc976dd19b38af62ada6c3..d5d4643a48da0fe6517763508ff8b76062b76cb4 100644 --- a/hbase-common/src/main/java/org/apache/hadoop/hbase/HBaseInterfaceAudience.java +++ b/hbase-common/src/main/java/org/apache/hadoop/hbase/HBaseInterfaceAudience.java @@ -48,4 +48,9 @@ public final class HBaseInterfaceAudience { * for class name, and arguments. */ public static final String TOOLS = "Tools"; + + /** + * Denotes classes used by hbck tool for fixing inconsistent state of HBase. + */ + public static final String HBCK = "HBCK"; } diff --git a/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestMultiTableInputFormatBase.java b/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestMultiTableInputFormatBase.java index efc59c7844a57158a8d695cc0c058eab44a46027..791394550e22827e62c9480b43739805f171b6fc 100644 --- a/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestMultiTableInputFormatBase.java +++ b/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestMultiTableInputFormatBase.java @@ -38,6 +38,7 @@ import org.apache.hadoop.hbase.client.BufferedMutator; import org.apache.hadoop.hbase.client.BufferedMutatorParams; import org.apache.hadoop.hbase.client.ClusterConnection; import org.apache.hadoop.hbase.client.Connection; +import org.apache.hadoop.hbase.client.Hbck; import org.apache.hadoop.hbase.client.RegionInfoBuilder; import org.apache.hadoop.hbase.client.RegionLocator; import org.apache.hadoop.hbase.client.Result; @@ -215,6 +216,11 @@ public class TestMultiTableInputFormatBase { return admin; } + @Override + public Hbck getHbck() throws IOException { + return Mockito.mock(Hbck.class); + } + @Override public Table getTable(TableName tableName) throws IOException { Table table = Mockito.mock(Table.class); diff --git a/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestTableInputFormatBase.java b/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestTableInputFormatBase.java index 29a92ee75c06c80d78ed896470e5a977b6e6f791..54f502ffdf10078d2e0f652ea477eefddfc8d258 100644 --- a/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestTableInputFormatBase.java +++ b/hbase-mapreduce/src/test/java/org/apache/hadoop/hbase/mapreduce/TestTableInputFormatBase.java @@ -42,6 +42,7 @@ import org.apache.hadoop.hbase.client.BufferedMutator; import org.apache.hadoop.hbase.client.BufferedMutatorParams; import org.apache.hadoop.hbase.client.ClusterConnection; import org.apache.hadoop.hbase.client.Connection; +import org.apache.hadoop.hbase.client.Hbck; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.RegionInfoBuilder; import org.apache.hadoop.hbase.client.RegionLocator; @@ -273,6 +274,11 @@ public class TestTableInputFormatBase { return admin; } + @Override + public Hbck getHbck() throws IOException { + return mock(Hbck.class); + } + @Override public void close() throws IOException { } diff --git a/hbase-protocol-shaded/src/main/protobuf/Master.proto b/hbase-protocol-shaded/src/main/protobuf/Master.proto index c2ab18017f4bc2319180d3490792a21e2808d61d..69e0f32d07e4223d7dc924b8b5c7b7449346a765 100644 --- a/hbase-protocol-shaded/src/main/protobuf/Master.proto +++ b/hbase-protocol-shaded/src/main/protobuf/Master.proto @@ -485,6 +485,11 @@ message GetTableStateResponse { required TableState table_state = 1; } +message SetTableStateInMetaRequest { + required TableName table_name = 1; + required TableState table_state = 2; +} + message GetClusterStatusRequest { repeated Option options = 1; } @@ -991,3 +996,9 @@ service MasterService { returns(ClearDeadServersResponse); } + +service HbckService { + /** Update state of the table in meta only*/ + rpc SetTableStateInMeta(SetTableStateInMetaRequest) + returns(GetTableStateResponse); +} diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/SharedConnection.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/SharedConnection.java index 9ad55b71776c786855fbd25904908a3b8a363b91..89fee592d7b5abf0c61ccbbcd366d6100b3994c9 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/SharedConnection.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/SharedConnection.java @@ -25,6 +25,7 @@ import org.apache.hadoop.hbase.client.Admin; import org.apache.hadoop.hbase.client.BufferedMutator; import org.apache.hadoop.hbase.client.BufferedMutatorParams; import org.apache.hadoop.hbase.client.Connection; +import org.apache.hadoop.hbase.client.Hbck; import org.apache.hadoop.hbase.client.RegionLocator; import org.apache.hadoop.hbase.client.TableBuilder; import org.apache.yetus.audience.InterfaceAudience; @@ -86,6 +87,11 @@ public class SharedConnection implements Connection { return this.conn.getAdmin(); } + @Override + public Hbck getHbck() throws IOException { + return this.conn.getHbck(); + } + @Override public TableBuilder getTableBuilder(TableName tableName, ExecutorService pool) { return this.conn.getTableBuilder(tableName, pool); diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java index a4d9ff84f0a151ffb204f7f8a90b636c8c17d67c..87402b03f057c2f60b3bd838a3214cb6e836377c 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java @@ -43,6 +43,7 @@ import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.UnknownRegionException; import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; +import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.MasterSwitchType; import org.apache.hadoop.hbase.client.RegionInfo; import org.apache.hadoop.hbase.client.RegionInfoBuilder; @@ -177,6 +178,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableNa import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableNamesResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableStateRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableStateResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.HbckService; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsBalancerEnabledRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsBalancerEnabledResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.IsCatalogJanitorEnabledRequest; @@ -241,6 +243,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaRe import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetQuotaResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetSplitOrMergeEnabledRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetSplitOrMergeEnabledResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetTableStateInMetaRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ShutdownRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ShutdownResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SnapshotRequest; @@ -305,7 +308,7 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.Snapshot @SuppressWarnings("deprecation") public class MasterRpcServices extends RSRpcServices implements MasterService.BlockingInterface, RegionServerStatusService.BlockingInterface, - LockService.BlockingInterface { + LockService.BlockingInterface, HbckService.BlockingInterface { private static final Logger LOG = LoggerFactory.getLogger(MasterRpcServices.class.getName()); private final HMaster master; @@ -433,6 +436,8 @@ public class MasterRpcServices extends RSRpcServices RegionServerStatusService.BlockingInterface.class)); bssi.add(new BlockingServiceAndInterface(LockService.newReflectiveBlockingService(this), LockService.BlockingInterface.class)); + bssi.add(new BlockingServiceAndInterface(HbckService.newReflectiveBlockingService(this), + HbckService.BlockingInterface.class)); bssi.addAll(super.getServices()); return bssi; } @@ -2302,4 +2307,29 @@ public class MasterRpcServices extends RSRpcServices throw new ServiceException(e); } } + + // HBCK Services + + /** + * Update state of the table in meta only. This is required by hbck in some situations to cleanup + * stuck assign/ unassign regions procedures for the table. + * + * @return previous state of the table + */ + @Override + public GetTableStateResponse setTableStateInMeta(RpcController controller, + SetTableStateInMetaRequest request) throws ServiceException { + Connection conn = master.getConnection(); + TableName tn = ProtobufUtil.toTableName(request.getTableName()); + + try { + HBaseProtos.TableState prevState = MetaTableAccessor.getTableState(conn, tn).convert(); + MetaTableAccessor.updateTableState(conn, tn, + TableState.convert(tn, request.getTableState()).getState()); + return GetTableStateResponse.newBuilder().setTableState(prevState).build(); + } catch (Exception e) { + throw new ServiceException(e); + } + } + } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java index b938d2834f265c69389f74ee179aed96f9d2d534..55a9fc4935aea98a274fe1d9864f5e54a2b38b73 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/HBaseTestingUtility.java @@ -73,6 +73,8 @@ import org.apache.hadoop.hbase.client.Delete; import org.apache.hadoop.hbase.client.Durability; import org.apache.hadoop.hbase.client.Get; import org.apache.hadoop.hbase.client.HBaseAdmin; +import org.apache.hadoop.hbase.client.HBaseHbck; +import org.apache.hadoop.hbase.client.Hbck; import org.apache.hadoop.hbase.client.ImmutableHRegionInfo; import org.apache.hadoop.hbase.client.ImmutableHTableDescriptor; import org.apache.hadoop.hbase.client.Put; @@ -2820,7 +2822,18 @@ public class HBaseTestingUtility extends HBaseZKTestingUtility { private HBaseAdmin hbaseAdmin = null; + /** + * Returns an Hbck instance which is shared between HBaseTestingUtility instance users. + * Closing it has no effect, it will be closed automatically when the cluster shutdowns + */ + public synchronized Hbck getHbck() throws IOException { + if (hbaseHbck == null){ + this.hbaseHbck = (HBaseHbck) getConnection().getHbck(); + } + return hbaseHbck; + } + private HBaseHbck hbaseHbck = null; /** * Unassign the named region. diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java new file mode 100644 index 0000000000000000000000000000000000000000..ea1817d47735b83747e7c70ec4ad03e80bb53e9e --- /dev/null +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestHbck.java @@ -0,0 +1,104 @@ +/* + * 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.client; + +import org.apache.hadoop.hbase.HBaseClassTestRule; +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.testclassification.ClientTests; +import org.apache.hadoop.hbase.testclassification.LargeTests; +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.experimental.categories.Category; +import org.junit.rules.TestName; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.IOException; + +import static junit.framework.TestCase.assertTrue; + +/** + * Class to test HBaseHbck. + * Spins up the minicluster once at test start and then takes it down afterward. + * Add any testing of HBaseHbck functionality here. + */ +@Category({LargeTests.class, ClientTests.class}) +public class TestHbck { + @ClassRule + public static final HBaseClassTestRule CLASS_RULE = + HBaseClassTestRule.forClass(TestHbck.class); + + private static final Logger LOG = LoggerFactory.getLogger(TestHbck.class); + private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); + private Admin admin; + private Hbck hbck; + + @Rule + public TestName name = new TestName(); + + private static final TableName tableName = TableName.valueOf(TestHbck.class.getSimpleName()); + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + TEST_UTIL.getConfiguration().setInt("hbase.regionserver.msginterval", 100); + TEST_UTIL.getConfiguration().setInt("hbase.client.pause", 250); + TEST_UTIL.getConfiguration().setInt("hbase.client.retries.number", 6); + TEST_UTIL.getConfiguration().setBoolean("hbase.master.enabletable.roundrobin", true); + TEST_UTIL.startMiniCluster(3); + + TEST_UTIL.createTable(tableName, "family1"); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + TEST_UTIL.shutdownMiniCluster(); + } + + @Before + public void setUp() throws Exception { + this.admin = TEST_UTIL.getAdmin(); + this.hbck = TEST_UTIL.getHbck(); + } + + @After + public void tearDown() throws Exception { + for (HTableDescriptor htd : this.admin.listTables()) { + TEST_UTIL.deleteTable(htd.getTableName()); + } + } + + @Test + public void testSetTableStateInMeta() throws IOException { + try { + assertTrue(hbck.setTableStateInMeta(new TableState(tableName, TableState.State.DISABLED)) + .isEnabled()); + assertTrue(hbck.setTableStateInMeta(new TableState(tableName, TableState.State.ENABLED)) + .isDisabled()); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/regionserver/TestWALEntrySinkFilter.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/regionserver/TestWALEntrySinkFilter.java index fd9ff2924bbba5d59bc74c67ced34420bc30abc2..ba397131d15bc1bf7287ff7813502f78cccf2fcf 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/regionserver/TestWALEntrySinkFilter.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/replication/regionserver/TestWALEntrySinkFilter.java @@ -49,6 +49,7 @@ import org.apache.hadoop.hbase.client.Connection; import org.apache.hadoop.hbase.client.Delete; import org.apache.hadoop.hbase.client.Durability; import org.apache.hadoop.hbase.client.Get; +import org.apache.hadoop.hbase.client.Hbck; import org.apache.hadoop.hbase.client.Increment; import org.apache.hadoop.hbase.client.Put; import org.apache.hadoop.hbase.client.RegionLocator; @@ -257,6 +258,11 @@ public class TestWALEntrySinkFilter { return null; } + @Override + public Hbck getHbck() throws IOException { + return null; + } + @Override public void close() throws IOException { diff --git a/hbase-spark/src/test/scala/org/apache/hadoop/hbase/spark/HBaseConnectionCacheSuite.scala b/hbase-spark/src/test/scala/org/apache/hadoop/hbase/spark/HBaseConnectionCacheSuite.scala index 5b42bd96b4c42d08dbc518a01a339f6ea5f63f9c..809a755869f727f53f9377c589bcc9bad0e8e863 100644 --- a/hbase-spark/src/test/scala/org/apache/hadoop/hbase/spark/HBaseConnectionCacheSuite.scala +++ b/hbase-spark/src/test/scala/org/apache/hadoop/hbase/spark/HBaseConnectionCacheSuite.scala @@ -21,7 +21,7 @@ import java.util.concurrent.ExecutorService import scala.util.Random import org.apache.hadoop.hbase.client.{BufferedMutator, Table, RegionLocator, - Connection, BufferedMutatorParams, Admin, TableBuilder} + Connection, BufferedMutatorParams, Admin, Hbck, TableBuilder} import org.apache.hadoop.conf.Configuration import org.apache.hadoop.hbase.TableName import org.scalatest.FunSuite @@ -49,6 +49,7 @@ class ConnectionMocker extends Connection { def getBufferedMutator (params: BufferedMutatorParams): BufferedMutator = null def getBufferedMutator (tableName: TableName): BufferedMutator = null def getAdmin: Admin = null + def getHbck: Hbck = null def getTableBuilder(tableName: TableName, pool: ExecutorService): TableBuilder = null def close(): Unit = { -- 2.16.1