HBASE-17600 Implement get/create/modify/delete/list namespace admin operations
Project: http://git-wip-us.apache.org/repos/asf/hbase/repo Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/4ff838df Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/4ff838df Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/4ff838df Branch: refs/heads/hbase-12439 Commit: 4ff838df13df737568893a9f5dfde2ae38d4bf69 Parents: 9214ad6 Author: Guanghao Zhang <zg...@apache.org> Authored: Thu Mar 9 10:32:46 2017 +0800 Committer: Guanghao Zhang <zg...@apache.org> Committed: Thu Mar 9 10:32:46 2017 +0800 ---------------------------------------------------------------------- .../apache/hadoop/hbase/client/AsyncAdmin.java | 32 + .../hadoop/hbase/client/AsyncHBaseAdmin.java | 121 +- .../hbase/client/AsyncRpcRetryingCaller.java | 6 +- .../hbase/shaded/protobuf/ProtobufUtil.java | 25 +- .../hbase/shaded/protobuf/RequestConverter.java | 51 + .../hadoop/hbase/client/TestAsyncAdmin.java | 1087 ------------------ .../hadoop/hbase/client/TestAsyncAdminBase.java | 67 ++ .../hbase/client/TestAsyncBalancerAdminApi.java | 51 + .../client/TestAsyncNamespaceAdminApi.java | 189 +++ .../hbase/client/TestAsyncRegionAdminApi.java | 203 ++++ .../hbase/client/TestAsyncTableAdminApi.java | 838 ++++++++++++++ 11 files changed, 1575 insertions(+), 1095 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/hbase/blob/4ff838df/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java ---------------------------------------------------------------------- diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java index 0abd507..630ae47 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncAdmin.java @@ -24,6 +24,7 @@ import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.HTableDescriptor; import org.apache.hadoop.hbase.ServerName; +import org.apache.hadoop.hbase.NamespaceDescriptor; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.classification.InterfaceStability; @@ -254,6 +255,37 @@ public interface AsyncAdmin { final HColumnDescriptor columnFamily); /** + * Create a new namespace. + * @param descriptor descriptor which describes the new namespace + */ + CompletableFuture<Void> createNamespace(final NamespaceDescriptor descriptor); + + /** + * Modify an existing namespace. + * @param descriptor descriptor which describes the new namespace + */ + CompletableFuture<Void> modifyNamespace(final NamespaceDescriptor descriptor); + + /** + * Delete an existing namespace. Only empty namespaces (no tables) can be removed. + * @param name namespace name + */ + CompletableFuture<Void> deleteNamespace(final String name); + + /** + * Get a namespace descriptor by name + * @param name name of namespace descriptor + * @return A descriptor wrapped by a {@link CompletableFuture}. + */ + CompletableFuture<NamespaceDescriptor> getNamespaceDescriptor(final String name); + + /** + * List available namespace descriptors + * @return List of descriptors wrapped by a {@link CompletableFuture}. + */ + CompletableFuture<NamespaceDescriptor[]> listNamespaceDescriptors(); + + /** * Turn the load balancer on or off. * @param on * @return Previous balancer value wrapped by a {@link CompletableFuture}. http://git-wip-us.apache.org/repos/asf/hbase/blob/4ff838df/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java ---------------------------------------------------------------------- diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java index 3876570..e2dc3d5 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncHBaseAdmin.java @@ -38,6 +38,7 @@ import org.apache.hadoop.hbase.MetaTableAccessor; import org.apache.hadoop.hbase.NotServingRegionException; import org.apache.hadoop.hbase.RegionLocations; import org.apache.hadoop.hbase.ServerName; +import org.apache.hadoop.hbase.NamespaceDescriptor; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.AsyncMetaTableAccessor; import org.apache.hadoop.hbase.HConstants; @@ -60,12 +61,18 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AddColumnR import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AddColumnResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.BalanceRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.BalanceResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateNamespaceRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateNamespaceResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteNamespaceRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteNamespaceResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DisableTableRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DisableTableResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableTableRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableTableResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteColumnRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteColumnResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetNamespaceDescriptorRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetNamespaceDescriptorResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProcedureResultRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetProcedureResultResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetSchemaAlterStatusRequest; @@ -80,9 +87,13 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteTabl import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteTableResponse; 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.ListNamespaceDescriptorsRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListNamespaceDescriptorsResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.MasterService; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyColumnRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyColumnResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyNamespaceRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyNamespaceResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetBalancerRunningRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetBalancerRunningResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.TruncateTableRequest; @@ -208,9 +219,9 @@ public class AsyncHBaseAdmin implements AsyncAdmin { private <PREQ, PRESP> CompletableFuture<Void> procedureCall(PREQ preq, MasterRpcCall<PRESP, PREQ> rpcCall, Converter<Long, PRESP> respConverter, - TableProcedureBiConsumer consumer) { + ProcedureBiConsumer consumer) { CompletableFuture<Long> procFuture = this - .<Long>newMasterCaller() + .<Long> newMasterCaller() .action( (controller, stub) -> this.<PREQ, PRESP, Long> call(controller, stub, preq, rpcCall, respConverter)).call(); @@ -468,6 +479,54 @@ public class AsyncHBaseAdmin implements AsyncAdmin { } @Override + public CompletableFuture<Void> createNamespace(NamespaceDescriptor descriptor) { + return this.<CreateNamespaceRequest, CreateNamespaceResponse> procedureCall( + RequestConverter.buildCreateNamespaceRequest(descriptor), + (s, c, req, done) -> s.createNamespace(c, req, done), (resp) -> resp.getProcId(), + new CreateNamespaceProcedureBiConsumer(this, descriptor.getName())); + } + + @Override + public CompletableFuture<Void> modifyNamespace(NamespaceDescriptor descriptor) { + return this.<ModifyNamespaceRequest, ModifyNamespaceResponse> procedureCall( + RequestConverter.buildModifyNamespaceRequest(descriptor), + (s, c, req, done) -> s.modifyNamespace(c, req, done), (resp) -> resp.getProcId(), + new ModifyNamespaceProcedureBiConsumer(this, descriptor.getName())); + } + + @Override + public CompletableFuture<Void> deleteNamespace(String name) { + return this.<DeleteNamespaceRequest, DeleteNamespaceResponse> procedureCall( + RequestConverter.buildDeleteNamespaceRequest(name), + (s, c, req, done) -> s.deleteNamespace(c, req, done), (resp) -> resp.getProcId(), + new ModifyNamespaceProcedureBiConsumer(this, name)); + } + + @Override + public CompletableFuture<NamespaceDescriptor> getNamespaceDescriptor(String name) { + return this + .<NamespaceDescriptor> newMasterCaller() + .action( + (controller, stub) -> this + .<GetNamespaceDescriptorRequest, GetNamespaceDescriptorResponse, NamespaceDescriptor> call( + controller, stub, RequestConverter.buildGetNamespaceDescriptorRequest(name), (s, c, + req, done) -> s.getNamespaceDescriptor(c, req, done), (resp) -> ProtobufUtil + .toNamespaceDescriptor(resp.getNamespaceDescriptor()))).call(); + } + + @Override + public CompletableFuture<NamespaceDescriptor[]> listNamespaceDescriptors() { + return this + .<NamespaceDescriptor[]> newMasterCaller() + .action( + (controller, stub) -> this + .<ListNamespaceDescriptorsRequest, ListNamespaceDescriptorsResponse, NamespaceDescriptor[]> call( + controller, stub, ListNamespaceDescriptorsRequest.newBuilder().build(), (s, c, req, + done) -> s.listNamespaceDescriptors(c, req, done), (resp) -> ProtobufUtil + .getNamespaceDescriptorArray(resp))).call(); + } + + @Override public CompletableFuture<Boolean> setBalancerRunning(final boolean on) { return this .<Boolean>newMasterCaller() @@ -674,6 +733,31 @@ public class AsyncHBaseAdmin implements AsyncAdmin { } } + private abstract class NamespaceProcedureBiConsumer extends ProcedureBiConsumer { + protected final String namespaceName; + + NamespaceProcedureBiConsumer(final AsyncAdmin admin, final String namespaceName) { + super(admin); + this.namespaceName = namespaceName; + } + + abstract String getOperationType(); + + String getDescription() { + return "Operation: " + getOperationType() + ", Namespace: " + namespaceName; + } + + @Override + void onFinished() { + LOG.info(getDescription() + " completed"); + } + + @Override + void onError(Throwable error) { + LOG.info(getDescription() + " failed with " + error.getMessage()); + } + } + private class CreateTableProcedureBiConsumer extends TableProcedureBiConsumer { CreateTableProcedureBiConsumer(AsyncAdmin admin, TableName tableName) { @@ -768,6 +852,39 @@ public class AsyncHBaseAdmin implements AsyncAdmin { } } + private class CreateNamespaceProcedureBiConsumer extends NamespaceProcedureBiConsumer { + + CreateNamespaceProcedureBiConsumer(AsyncAdmin admin, String namespaceName) { + super(admin, namespaceName); + } + + String getOperationType() { + return "CREATE_NAMESPACE"; + } + } + + private class DeleteNamespaceProcedureBiConsumer extends NamespaceProcedureBiConsumer { + + DeleteNamespaceProcedureBiConsumer(AsyncAdmin admin, String namespaceName) { + super(admin, namespaceName); + } + + String getOperationType() { + return "DELETE_NAMESPACE"; + } + } + + private class ModifyNamespaceProcedureBiConsumer extends NamespaceProcedureBiConsumer { + + ModifyNamespaceProcedureBiConsumer(AsyncAdmin admin, String namespaceName) { + super(admin, namespaceName); + } + + String getOperationType() { + return "MODIFY_NAMESPACE"; + } + } + private CompletableFuture<Void> waitProcedureResult(CompletableFuture<Long> procFuture) { CompletableFuture<Void> future = new CompletableFuture<>(); procFuture.whenComplete((procId, error) -> { http://git-wip-us.apache.org/repos/asf/hbase/blob/4ff838df/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRpcRetryingCaller.java ---------------------------------------------------------------------- diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRpcRetryingCaller.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRpcRetryingCaller.java index d449db1..c753383 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRpcRetryingCaller.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/AsyncRpcRetryingCaller.java @@ -114,6 +114,10 @@ public abstract class AsyncRpcRetryingCaller<T> { protected void onError(Throwable error, Supplier<String> errMsg, Consumer<Throwable> updateCachedLocation) { error = translateException(error); + if (error instanceof DoNotRetryIOException) { + future.completeExceptionally(error); + return; + } if (tries > startLogErrorsCnt) { LOG.warn(errMsg.get() + ", tries = " + tries + ", maxAttempts = " + maxAttempts + ", timeout = " + TimeUnit.NANOSECONDS.toMillis(operationTimeoutNs) @@ -122,7 +126,7 @@ public abstract class AsyncRpcRetryingCaller<T> { RetriesExhaustedException.ThrowableWithExtraContext qt = new RetriesExhaustedException.ThrowableWithExtraContext( error, EnvironmentEdgeManager.currentTime(), ""); exceptions.add(qt); - if (error instanceof DoNotRetryIOException || tries >= maxAttempts) { + if (tries >= maxAttempts) { completeExceptionally(); return; } http://git-wip-us.apache.org/repos/asf/hbase/blob/4ff838df/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java ---------------------------------------------------------------------- diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java index 38ae04a..10827c3 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/ProtobufUtil.java @@ -151,6 +151,8 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MapReduceProtos; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateTableRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetTableDescriptorsResponse; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListNamespaceDescriptorsRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ListNamespaceDescriptorsResponse; import org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos; import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerReportRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest; @@ -394,6 +396,21 @@ public final class ProtobufUtil { } /** + * Get NamespaceDescriptor[] from ListNamespaceDescriptorsResponse protobuf + * @param proto the ListNamespaceDescriptorsResponse + * @return NamespaceDescriptor[] + */ + public static NamespaceDescriptor[] getNamespaceDescriptorArray( + ListNamespaceDescriptorsResponse proto) { + List<HBaseProtos.NamespaceDescriptor> list = proto.getNamespaceDescriptorList(); + NamespaceDescriptor[] res = new NamespaceDescriptor[list.size()]; + for (int i = 0; i < list.size(); i++) { + res[i] = ProtobufUtil.toNamespaceDescriptor(list.get(i)); + } + return res; + } + + /** * Get HTableDescriptor[] from GetTableDescriptorsResponse protobuf * * @param proto the GetTableDescriptorsResponse @@ -2136,11 +2153,9 @@ public final class ProtobufUtil { return b.build(); } - public static NamespaceDescriptor toNamespaceDescriptor( - HBaseProtos.NamespaceDescriptor desc) throws IOException { - NamespaceDescriptor.Builder b = - NamespaceDescriptor.create(desc.getName().toStringUtf8()); - for(HBaseProtos.NameStringPair prop : desc.getConfigurationList()) { + public static NamespaceDescriptor toNamespaceDescriptor(HBaseProtos.NamespaceDescriptor desc) { + NamespaceDescriptor.Builder b = NamespaceDescriptor.create(desc.getName().toStringUtf8()); + for (HBaseProtos.NameStringPair prop : desc.getConfigurationList()) { b.addConfiguration(prop.getName(), prop.getValue()); } return b.build(); http://git-wip-us.apache.org/repos/asf/hbase/blob/4ff838df/hbase-client/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/RequestConverter.java ---------------------------------------------------------------------- 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 998b3c0..a513d66 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 @@ -28,6 +28,7 @@ import org.apache.hadoop.hbase.HColumnDescriptor; import org.apache.hadoop.hbase.HConstants; import org.apache.hadoop.hbase.HRegionInfo; import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.NamespaceDescriptor; import org.apache.hadoop.hbase.ServerName; import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.classification.InterfaceAudience; @@ -80,11 +81,15 @@ import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AddColumnRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.AssignRegionRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.BalanceRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateNamespaceRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.CreateTableRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteColumnRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteNamespaceRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DeleteTableRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.DisableTableRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableCatalogJanitorRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetNamespaceDescriptorRequest; +import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.ModifyNamespaceRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.SetCleanerChoreRunningRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.EnableTableRequest; import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProtos.GetClusterStatusRequest; @@ -1644,4 +1649,50 @@ public final class RequestConverter { } return builder.build(); } + + /** + * Creates a protocol buffer CreateNamespaceRequest + * @param descriptor + * @return a CreateNamespaceRequest + */ + public static CreateNamespaceRequest buildCreateNamespaceRequest( + final NamespaceDescriptor descriptor) { + CreateNamespaceRequest.Builder builder = CreateNamespaceRequest.newBuilder(); + builder.setNamespaceDescriptor(ProtobufUtil.toProtoNamespaceDescriptor(descriptor)); + return builder.build(); + } + + /** + * Creates a protocol buffer ModifyNamespaceRequest + * @param descriptor + * @return a ModifyNamespaceRequest + */ + public static ModifyNamespaceRequest buildModifyNamespaceRequest( + final NamespaceDescriptor descriptor) { + ModifyNamespaceRequest.Builder builder = ModifyNamespaceRequest.newBuilder(); + builder.setNamespaceDescriptor(ProtobufUtil.toProtoNamespaceDescriptor(descriptor)); + return builder.build(); + } + + /** + * Creates a protocol buffer DeleteNamespaceRequest + * @param name + * @return a DeleteNamespaceRequest + */ + public static DeleteNamespaceRequest buildDeleteNamespaceRequest(final String name) { + DeleteNamespaceRequest.Builder builder = DeleteNamespaceRequest.newBuilder(); + builder.setNamespaceName(name); + return builder.build(); + } + + /** + * Creates a protocol buffer GetNamespaceDescriptorRequest + * @param name + * @return a GetNamespaceDescriptorRequest + */ + public static GetNamespaceDescriptorRequest buildGetNamespaceDescriptorRequest(final String name) { + GetNamespaceDescriptorRequest.Builder builder = GetNamespaceDescriptorRequest.newBuilder(); + builder.setNamespaceName(name); + return builder.build(); + } } http://git-wip-us.apache.org/repos/asf/hbase/blob/4ff838df/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAdmin.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAdmin.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAdmin.java deleted file mode 100644 index 950d77d..0000000 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAdmin.java +++ /dev/null @@ -1,1087 +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.client; - -import static org.apache.hadoop.hbase.client.AsyncProcess.START_LOG_ERRORS_AFTER_COUNT_KEY; -import static org.apache.hadoop.hbase.TableName.META_TABLE_NAME; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.fail; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; -import java.util.concurrent.CompletionException; -import java.util.regex.Pattern; - -import org.apache.commons.io.IOUtils; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.fs.Path; -import org.apache.hadoop.hbase.AsyncMetaTableAccessor; -import org.apache.hadoop.hbase.HBaseTestingUtility; -import org.apache.hadoop.hbase.HColumnDescriptor; -import org.apache.hadoop.hbase.HConstants; -import org.apache.hadoop.hbase.HRegionInfo; -import org.apache.hadoop.hbase.HRegionLocation; -import org.apache.hadoop.hbase.HTableDescriptor; -import org.apache.hadoop.hbase.ServerName; -import org.apache.hadoop.hbase.TableName; -import org.apache.hadoop.hbase.TableNotEnabledException; -import org.apache.hadoop.hbase.master.MasterFileSystem; -import org.apache.hadoop.hbase.regionserver.HRegionServer; -import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil; -import org.apache.hadoop.hbase.testclassification.ClientTests; -import org.apache.hadoop.hbase.testclassification.LargeTests; -import org.apache.hadoop.hbase.util.Bytes; -import org.apache.hadoop.hbase.util.FSTableDescriptors; -import org.apache.hadoop.hbase.util.FSUtils; -import org.apache.hadoop.hbase.util.Pair; -import org.junit.AfterClass; -import org.junit.Assert; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.experimental.categories.Category; -import org.junit.rules.TestName; - -/** - * Class to test AsyncAdmin. - */ -@Category({LargeTests.class, ClientTests.class}) -public class TestAsyncAdmin { - - private static final Log LOG = LogFactory.getLog(TestAdmin1.class); - private final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); - private static byte[] FAMILY = Bytes.toBytes("testFamily"); - private static final byte[] FAMILY_0 = Bytes.toBytes("cf0"); - private static final byte[] FAMILY_1 = Bytes.toBytes("cf1"); - - private static AsyncConnection ASYNC_CONN; - private AsyncAdmin admin; - - @Rule - public TestName name = new TestName(); - - @BeforeClass - public static void setUpBeforeClass() throws Exception { - TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_PAUSE, 10); - TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 3); - TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 1000); - TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_OPERATION_TIMEOUT, 3000); - TEST_UTIL.getConfiguration().setInt(START_LOG_ERRORS_AFTER_COUNT_KEY, 0); - TEST_UTIL.startMiniCluster(1); - ASYNC_CONN = ConnectionFactory.createAsyncConnection(TEST_UTIL.getConfiguration()).get(); - } - - @AfterClass - public static void tearDownAfterClass() throws Exception { - IOUtils.closeQuietly(ASYNC_CONN); - TEST_UTIL.shutdownMiniCluster(); - } - - @Before - public void setUp() throws Exception { - this.admin = ASYNC_CONN.getAdmin(); - } - - @Test - public void testTableExist() throws Exception { - final TableName tableName = TableName.valueOf(name.getMethodName()); - boolean exist; - exist = admin.tableExists(tableName).get(); - assertEquals(false, exist); - TEST_UTIL.createTable(tableName, FAMILY); - exist = admin.tableExists(tableName).get(); - assertEquals(true, exist); - exist = admin.tableExists(TableName.META_TABLE_NAME).get(); - assertEquals(true, exist); - } - - @Test - public void testListTables() throws Exception { - int numTables = admin.listTables().get().length; - final TableName tableName1 = TableName.valueOf(name.getMethodName() + "1"); - final TableName tableName2 = TableName.valueOf(name.getMethodName() + "2"); - final TableName tableName3 = TableName.valueOf(name.getMethodName() + "3"); - TableName[] tables = new TableName[] { tableName1, tableName2, tableName3 }; - for (int i = 0; i < tables.length; i++) { - TEST_UTIL.createTable(tables[i], FAMILY); - } - - HTableDescriptor[] tableDescs = admin.listTables().get(); - int size = tableDescs.length; - assertTrue(size >= tables.length); - for (int i = 0; i < tables.length && i < size; i++) { - boolean found = false; - for (int j = 0; j < tableDescs.length; j++) { - if (tableDescs[j].getTableName().equals(tables[i])) { - found = true; - break; - } - } - assertTrue("Not found: " + tables[i], found); - } - - TableName[] tableNames = admin.listTableNames().get(); - size = tableNames.length; - assertTrue(size == (numTables + tables.length)); - for (int i = 0; i < tables.length && i < size; i++) { - boolean found = false; - for (int j = 0; j < tableNames.length; j++) { - if (tableNames[j].equals(tables[i])) { - found = true; - break; - } - } - assertTrue("Not found: " + tables[i], found); - } - - for (int i = 0; i < tables.length; i++) { - TEST_UTIL.deleteTable(tables[i]); - } - - tableDescs = admin.listTables((Pattern) null, true).get(); - assertTrue("Not found system tables", tableDescs.length > 0); - tableNames = admin.listTableNames((Pattern) null, true).get(); - assertTrue("Not found system tables", tableNames.length > 0); - } - - @Test(timeout = 300000) - public void testGetTableDescriptor() throws Exception { - HColumnDescriptor fam1 = new HColumnDescriptor("fam1"); - HColumnDescriptor fam2 = new HColumnDescriptor("fam2"); - HColumnDescriptor fam3 = new HColumnDescriptor("fam3"); - HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(name.getMethodName())); - htd.addFamily(fam1); - htd.addFamily(fam2); - htd.addFamily(fam3); - admin.createTable(htd).join(); - HTableDescriptor confirmedHtd = admin.getTableDescriptor(htd.getTableName()).get(); - assertEquals(htd.compareTo(confirmedHtd), 0); - } - - @Test(timeout = 300000) - public void testCreateTable() throws Exception { - HTableDescriptor[] tables = admin.listTables().get(); - int numTables = tables.length; - final TableName tableName = TableName.valueOf(name.getMethodName()); - admin.createTable(new HTableDescriptor(tableName).addFamily(new HColumnDescriptor(FAMILY))) - .join(); - tables = admin.listTables().get(); - assertEquals(numTables + 1, tables.length); - assertTrue("Table must be enabled.", TEST_UTIL.getHBaseCluster().getMaster() - .getTableStateManager().isTableState(tableName, TableState.State.ENABLED)); - assertEquals(TableState.State.ENABLED, getStateFromMeta(tableName)); - } - - private TableState.State getStateFromMeta(TableName table) throws Exception { - Optional<TableState> state = AsyncMetaTableAccessor.getTableState( - ASYNC_CONN.getRawTable(META_TABLE_NAME), table).get(); - assertTrue(state.isPresent()); - return state.get().getState(); - } - - @Test(timeout = 300000) - public void testCreateTableNumberOfRegions() throws Exception { - final TableName tableName = TableName.valueOf(name.getMethodName()); - HTableDescriptor desc = new HTableDescriptor(tableName); - desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); - admin.createTable(desc).join(); - List<HRegionLocation> regions; - try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(tableName)) { - regions = l.getAllRegionLocations(); - assertEquals("Table should have only 1 region", 1, regions.size()); - } - - final TableName tableName2 = TableName.valueOf(tableName.getNameAsString() + "_2"); - desc = new HTableDescriptor(tableName2); - desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); - admin.createTable(desc, new byte[][] { new byte[] { 42 } }).join(); - try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(tableName2)) { - regions = l.getAllRegionLocations(); - assertEquals("Table should have only 2 region", 2, regions.size()); - } - - final TableName tableName3 = TableName.valueOf(tableName.getNameAsString() + "_3"); - desc = new HTableDescriptor(tableName3); - desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); - admin.createTable(desc, "a".getBytes(), "z".getBytes(), 3).join(); - try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(tableName3)) { - regions = l.getAllRegionLocations(); - assertEquals("Table should have only 3 region", 3, regions.size()); - } - - final TableName tableName4 = TableName.valueOf(tableName.getNameAsString() + "_4"); - desc = new HTableDescriptor(tableName4); - desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); - try { - admin.createTable(desc, "a".getBytes(), "z".getBytes(), 2).join(); - fail("Should not be able to create a table with only 2 regions using this API."); - } catch (CompletionException e) { - assertTrue(e.getCause() instanceof IllegalArgumentException); - } - - final TableName tableName5 = TableName.valueOf(tableName.getNameAsString() + "_5"); - desc = new HTableDescriptor(tableName5); - desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); - admin.createTable(desc, new byte[] { 1 }, new byte[] { 127 }, 16).join(); - try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(tableName5)) { - regions = l.getAllRegionLocations(); - assertEquals("Table should have 16 region", 16, regions.size()); - } - } - - @Test(timeout = 300000) - public void testCreateTableWithRegions() throws IOException, InterruptedException { - final TableName tableName = TableName.valueOf(name.getMethodName()); - - byte[][] splitKeys = { new byte[] { 1, 1, 1 }, new byte[] { 2, 2, 2 }, new byte[] { 3, 3, 3 }, - new byte[] { 4, 4, 4 }, new byte[] { 5, 5, 5 }, new byte[] { 6, 6, 6 }, - new byte[] { 7, 7, 7 }, new byte[] { 8, 8, 8 }, new byte[] { 9, 9, 9 }, }; - int expectedRegions = splitKeys.length + 1; - - HTableDescriptor desc = new HTableDescriptor(tableName); - desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); - admin.createTable(desc, splitKeys).join(); - - List<HRegionLocation> regions; - Iterator<HRegionLocation> hris; - HRegionInfo hri; - ClusterConnection conn = (ClusterConnection) TEST_UTIL.getConnection(); - try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(tableName)) { - regions = l.getAllRegionLocations(); - - assertEquals( - "Tried to create " + expectedRegions + " regions " + "but only found " + regions.size(), - expectedRegions, regions.size()); - System.err.println("Found " + regions.size() + " regions"); - - hris = regions.iterator(); - hri = hris.next().getRegionInfo(); - assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0); - assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[0])); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[0])); - assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[1])); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[1])); - assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[2])); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[2])); - assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[3])); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[3])); - assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[4])); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[4])); - assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[5])); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[5])); - assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[6])); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[6])); - assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[7])); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[7])); - assertTrue(Bytes.equals(hri.getEndKey(), splitKeys[8])); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), splitKeys[8])); - assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0); - - verifyRoundRobinDistribution(conn, l, expectedRegions); - } - - // Now test using start/end with a number of regions - - // Use 80 bit numbers to make sure we aren't limited - byte[] startKey = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; - byte[] endKey = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }; - - // Splitting into 10 regions, we expect (null,1) ... (9, null) - // with (1,2) (2,3) (3,4) (4,5) (5,6) (6,7) (7,8) (8,9) in the middle - - expectedRegions = 10; - - final TableName tableName2 = TableName.valueOf(tableName.getNameAsString() + "_2"); - - desc = new HTableDescriptor(tableName2); - desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); - admin.createTable(desc, startKey, endKey, expectedRegions).join(); - - try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(tableName2)) { - regions = l.getAllRegionLocations(); - assertEquals( - "Tried to create " + expectedRegions + " regions " + "but only found " + regions.size(), - expectedRegions, regions.size()); - System.err.println("Found " + regions.size() + " regions"); - - hris = regions.iterator(); - hri = hris.next().getRegionInfo(); - assertTrue(hri.getStartKey() == null || hri.getStartKey().length == 0); - assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 })); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 })); - assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 })); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 })); - assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 })); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 })); - assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 })); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 })); - assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 })); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 })); - assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 })); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 })); - assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 })); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 })); - assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 })); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 })); - assertTrue(Bytes.equals(hri.getEndKey(), new byte[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 })); - hri = hris.next().getRegionInfo(); - assertTrue(Bytes.equals(hri.getStartKey(), new byte[] { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 })); - assertTrue(hri.getEndKey() == null || hri.getEndKey().length == 0); - - verifyRoundRobinDistribution(conn, l, expectedRegions); - } - - // Try once more with something that divides into something infinite - - startKey = new byte[] { 0, 0, 0, 0, 0, 0 }; - endKey = new byte[] { 1, 0, 0, 0, 0, 0 }; - - expectedRegions = 5; - - final TableName tableName3 = TableName.valueOf(tableName.getNameAsString() + "_3"); - - desc = new HTableDescriptor(tableName3); - desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); - admin.createTable(desc, startKey, endKey, expectedRegions).join(); - - try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(tableName3)) { - regions = l.getAllRegionLocations(); - assertEquals( - "Tried to create " + expectedRegions + " regions " + "but only found " + regions.size(), - expectedRegions, regions.size()); - System.err.println("Found " + regions.size() + " regions"); - - verifyRoundRobinDistribution(conn, l, expectedRegions); - } - - // Try an invalid case where there are duplicate split keys - splitKeys = new byte[][] { new byte[] { 1, 1, 1 }, new byte[] { 2, 2, 2 }, - new byte[] { 3, 3, 3 }, new byte[] { 2, 2, 2 } }; - - final TableName tableName4 = TableName.valueOf(tableName.getNameAsString() + "_4"); - desc = new HTableDescriptor(tableName4); - desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); - try { - admin.createTable(desc, splitKeys).join(); - fail("Should not be able to create this table because of " + "duplicate split keys"); - } catch (CompletionException e) { - assertTrue(e.getCause() instanceof IllegalArgumentException); - } - } - - private void verifyRoundRobinDistribution(ClusterConnection c, RegionLocator regionLocator, - int expectedRegions) throws IOException { - int numRS = c.getCurrentNrHRS(); - List<HRegionLocation> regions = regionLocator.getAllRegionLocations(); - Map<ServerName, List<HRegionInfo>> server2Regions = new HashMap<>(); - regions.stream().forEach((loc) -> { - ServerName server = loc.getServerName(); - server2Regions.computeIfAbsent(server, (s) -> new ArrayList<>()).add(loc.getRegionInfo()); - }); - if (numRS >= 2) { - // Ignore the master region server, - // which contains less regions by intention. - numRS--; - } - float average = (float) expectedRegions / numRS; - int min = (int) Math.floor(average); - int max = (int) Math.ceil(average); - server2Regions.values().forEach((regionList) -> { - assertTrue(regionList.size() == min || regionList.size() == max); - }); - } - - @Test(timeout = 300000) - public void testCreateTableWithOnlyEmptyStartRow() throws IOException { - byte[] tableName = Bytes.toBytes(name.getMethodName()); - byte[][] splitKeys = new byte[1][]; - splitKeys[0] = HConstants.EMPTY_BYTE_ARRAY; - HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName)); - desc.addFamily(new HColumnDescriptor("col")); - try { - admin.createTable(desc, splitKeys).join(); - fail("Test case should fail as empty split key is passed."); - } catch (CompletionException e) { - assertTrue(e.getCause() instanceof IllegalArgumentException); - } - } - - @Test(timeout = 300000) - public void testCreateTableWithEmptyRowInTheSplitKeys() throws IOException { - byte[] tableName = Bytes.toBytes(name.getMethodName()); - byte[][] splitKeys = new byte[3][]; - splitKeys[0] = "region1".getBytes(); - splitKeys[1] = HConstants.EMPTY_BYTE_ARRAY; - splitKeys[2] = "region2".getBytes(); - HTableDescriptor desc = new HTableDescriptor(TableName.valueOf(tableName)); - desc.addFamily(new HColumnDescriptor("col")); - try { - admin.createTable(desc, splitKeys).join(); - fail("Test case should fail as empty split key is passed."); - } catch (CompletionException e) { - assertTrue(e.getCause() instanceof IllegalArgumentException); - } - } - - @Test(timeout = 300000) - public void testDeleteTable() throws Exception { - final TableName tableName = TableName.valueOf(name.getMethodName()); - admin.createTable(new HTableDescriptor(tableName).addFamily(new HColumnDescriptor(FAMILY))).join(); - assertTrue(admin.tableExists(tableName).get()); - TEST_UTIL.getAdmin().disableTable(tableName); - admin.deleteTable(tableName).join(); - assertFalse(admin.tableExists(tableName).get()); - } - - @Test(timeout = 300000) - public void testDeleteTables() throws Exception { - TableName[] tables = { TableName.valueOf(name.getMethodName() + "1"), - TableName.valueOf(name.getMethodName() + "2"), TableName.valueOf(name.getMethodName() + "3") }; - Arrays.stream(tables).map(HTableDescriptor::new) - .map((table) -> table.addFamily(new HColumnDescriptor(FAMILY))).forEach((table) -> { - admin.createTable(table).join(); - admin.tableExists(table.getTableName()).thenAccept((exist) -> assertTrue(exist)).join(); - try { - TEST_UTIL.getAdmin().disableTable(table.getTableName()); - } catch (Exception e) { - } - }); - HTableDescriptor[] failed = admin.deleteTables(Pattern.compile("testDeleteTables.*")).get(); - assertEquals(0, failed.length); - Arrays.stream(tables).forEach((table) -> { - admin.tableExists(table).thenAccept((exist) -> assertFalse(exist)).join(); - }); - } - - @Test(timeout = 300000) - public void testTruncateTable() throws IOException { - testTruncateTable(TableName.valueOf(name.getMethodName()), false); - } - - @Test(timeout = 300000) - public void testTruncateTablePreservingSplits() throws IOException { - testTruncateTable(TableName.valueOf(name.getMethodName()), true); - } - - private void testTruncateTable(final TableName tableName, boolean preserveSplits) - throws IOException { - byte[][] splitKeys = new byte[2][]; - splitKeys[0] = Bytes.toBytes(4); - splitKeys[1] = Bytes.toBytes(8); - - // Create & Fill the table - Table table = TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY, splitKeys); - try { - TEST_UTIL.loadNumericRows(table, HConstants.CATALOG_FAMILY, 0, 10); - assertEquals(10, TEST_UTIL.countRows(table)); - } finally { - table.close(); - } - assertEquals(3, TEST_UTIL.getHBaseCluster().getRegions(tableName).size()); - - // Truncate & Verify - TEST_UTIL.getAdmin().disableTable(tableName); - admin.truncateTable(tableName, preserveSplits).join(); - table = TEST_UTIL.getConnection().getTable(tableName); - try { - assertEquals(0, TEST_UTIL.countRows(table)); - } finally { - table.close(); - } - if (preserveSplits) { - assertEquals(3, TEST_UTIL.getHBaseCluster().getRegions(tableName).size()); - } else { - assertEquals(1, TEST_UTIL.getHBaseCluster().getRegions(tableName).size()); - } - } - - @Test(timeout = 300000) - public void testDisableAndEnableTable() throws Exception { - final byte[] row = Bytes.toBytes("row"); - final byte[] qualifier = Bytes.toBytes("qualifier"); - final byte[] value = Bytes.toBytes("value"); - final TableName tableName = TableName.valueOf(name.getMethodName()); - Table ht = TEST_UTIL.createTable(tableName, HConstants.CATALOG_FAMILY); - Put put = new Put(row); - put.addColumn(HConstants.CATALOG_FAMILY, qualifier, value); - ht.put(put); - Get get = new Get(row); - get.addColumn(HConstants.CATALOG_FAMILY, qualifier); - ht.get(get); - - this.admin.disableTable(ht.getName()).join(); - assertTrue("Table must be disabled.", TEST_UTIL.getHBaseCluster().getMaster() - .getTableStateManager().isTableState(ht.getName(), TableState.State.DISABLED)); - assertEquals(TableState.State.DISABLED, getStateFromMeta(tableName)); - - // Test that table is disabled - get = new Get(row); - get.addColumn(HConstants.CATALOG_FAMILY, qualifier); - boolean ok = false; - try { - ht.get(get); - } catch (TableNotEnabledException e) { - ok = true; - } - ok = false; - // verify that scan encounters correct exception - Scan scan = new Scan(); - try { - ResultScanner scanner = ht.getScanner(scan); - Result res = null; - do { - res = scanner.next(); - } while (res != null); - } catch (TableNotEnabledException e) { - ok = true; - } - assertTrue(ok); - this.admin.enableTable(tableName).join(); - assertTrue("Table must be enabled.", TEST_UTIL.getHBaseCluster().getMaster() - .getTableStateManager().isTableState(ht.getName(), TableState.State.ENABLED)); - assertEquals(TableState.State.ENABLED, getStateFromMeta(tableName)); - - // Test that table is enabled - try { - ht.get(get); - } catch (RetriesExhaustedException e) { - ok = false; - } - assertTrue(ok); - ht.close(); - } - - @Test(timeout = 300000) - public void testDisableAndEnableTables() throws Exception { - final byte[] row = Bytes.toBytes("row"); - final byte[] qualifier = Bytes.toBytes("qualifier"); - final byte[] value = Bytes.toBytes("value"); - final TableName tableName1 = TableName.valueOf(name.getMethodName() + "1"); - final TableName tableName2 = TableName.valueOf(name.getMethodName()); - Table ht1 = TEST_UTIL.createTable(tableName1, HConstants.CATALOG_FAMILY); - Table ht2 = TEST_UTIL.createTable(tableName2, HConstants.CATALOG_FAMILY); - Put put = new Put(row); - put.addColumn(HConstants.CATALOG_FAMILY, qualifier, value); - ht1.put(put); - ht2.put(put); - Get get = new Get(row); - get.addColumn(HConstants.CATALOG_FAMILY, qualifier); - ht1.get(get); - ht2.get(get); - - this.admin.disableTables("testDisableAndEnableTable.*").join(); - - // Test that tables are disabled - get = new Get(row); - get.addColumn(HConstants.CATALOG_FAMILY, qualifier); - boolean ok = false; - try { - ht1.get(get); - ht2.get(get); - } catch (org.apache.hadoop.hbase.DoNotRetryIOException e) { - ok = true; - } - - assertEquals(TableState.State.DISABLED, getStateFromMeta(tableName1)); - assertEquals(TableState.State.DISABLED, getStateFromMeta(tableName2)); - - assertTrue(ok); - this.admin.enableTables("testDisableAndEnableTable.*").join(); - - // Test that tables are enabled - try { - ht1.get(get); - } catch (IOException e) { - ok = false; - } - try { - ht2.get(get); - } catch (IOException e) { - ok = false; - } - assertTrue(ok); - - ht1.close(); - ht2.close(); - - assertEquals(TableState.State.ENABLED, getStateFromMeta(tableName1)); - assertEquals(TableState.State.ENABLED, getStateFromMeta(tableName2)); - } - - @Test(timeout = 300000) - public void testEnableTableRetainAssignment() throws Exception { - final TableName tableName = TableName.valueOf(name.getMethodName()); - byte[][] splitKeys = { new byte[] { 1, 1, 1 }, new byte[] { 2, 2, 2 }, new byte[] { 3, 3, 3 }, - new byte[] { 4, 4, 4 }, new byte[] { 5, 5, 5 }, new byte[] { 6, 6, 6 }, - new byte[] { 7, 7, 7 }, new byte[] { 8, 8, 8 }, new byte[] { 9, 9, 9 } }; - int expectedRegions = splitKeys.length + 1; - HTableDescriptor desc = new HTableDescriptor(tableName); - desc.addFamily(new HColumnDescriptor(HConstants.CATALOG_FAMILY)); - admin.createTable(desc, splitKeys).join(); - - try (RegionLocator l = TEST_UTIL.getConnection().getRegionLocator(tableName)) { - List<HRegionLocation> regions = l.getAllRegionLocations(); - - assertEquals( - "Tried to create " + expectedRegions + " regions " + "but only found " + regions.size(), - expectedRegions, regions.size()); - // Disable table. - admin.disableTable(tableName).join(); - // Enable table, use retain assignment to assign regions. - admin.enableTable(tableName).join(); - List<HRegionLocation> regions2 = l.getAllRegionLocations(); - - // Check the assignment. - assertEquals(regions.size(), regions2.size()); - assertTrue(regions2.containsAll(regions)); - } - } - - @Test(timeout = 300000) - public void testDisableCatalogTable() throws Exception { - try { - this.admin.disableTable(TableName.META_TABLE_NAME).join(); - fail("Expected to throw ConstraintException"); - } catch (Exception e) { - } - // Before the fix for HBASE-6146, the below table creation was failing as the hbase:meta table - // actually getting disabled by the disableTable() call. - HTableDescriptor htd = new HTableDescriptor(TableName.valueOf(name.getMethodName().getBytes())); - HColumnDescriptor hcd = new HColumnDescriptor("cf1".getBytes()); - htd.addFamily(hcd); - admin.createTable(htd).join(); - } - - @Test - public void testAddColumnFamily() throws IOException { - final TableName tableName = TableName.valueOf(name.getMethodName()); - // Create a table with two families - HTableDescriptor baseHtd = new HTableDescriptor(tableName); - baseHtd.addFamily(new HColumnDescriptor(FAMILY_0)); - admin.createTable(baseHtd).join(); - admin.disableTable(tableName).join(); - try { - // Verify the table descriptor - verifyTableDescriptor(tableName, FAMILY_0); - - // Modify the table removing one family and verify the descriptor - admin.addColumnFamily(tableName, new HColumnDescriptor(FAMILY_1)).join(); - verifyTableDescriptor(tableName, FAMILY_0, FAMILY_1); - } finally { - admin.deleteTable(tableName); - } - } - - @Test - public void testAddSameColumnFamilyTwice() throws Exception { - final TableName tableName = TableName.valueOf(name.getMethodName()); - // Create a table with one families - HTableDescriptor baseHtd = new HTableDescriptor(tableName); - baseHtd.addFamily(new HColumnDescriptor(FAMILY_0)); - admin.createTable(baseHtd).join(); - admin.disableTable(tableName).join(); - try { - // Verify the table descriptor - verifyTableDescriptor(tableName, FAMILY_0); - - // Modify the table removing one family and verify the descriptor - this.admin.addColumnFamily(tableName, new HColumnDescriptor(FAMILY_1)).join(); - verifyTableDescriptor(tableName, FAMILY_0, FAMILY_1); - - try { - // Add same column family again - expect failure - this.admin.addColumnFamily(tableName, new HColumnDescriptor(FAMILY_1)).join(); - Assert.fail("Delete a non-exist column family should fail"); - } catch (Exception e) { - // Expected. - } - } finally { - admin.deleteTable(tableName).join(); - } - } - - @Test - public void testModifyColumnFamily() throws Exception { - final TableName tableName = TableName.valueOf(name.getMethodName()); - - HColumnDescriptor cfDescriptor = new HColumnDescriptor(FAMILY_0); - int blockSize = cfDescriptor.getBlocksize(); - // Create a table with one families - HTableDescriptor baseHtd = new HTableDescriptor(tableName); - baseHtd.addFamily(cfDescriptor); - admin.createTable(baseHtd).join(); - admin.disableTable(tableName).join(); - try { - // Verify the table descriptor - verifyTableDescriptor(tableName, FAMILY_0); - - int newBlockSize = 2 * blockSize; - cfDescriptor.setBlocksize(newBlockSize); - - // Modify colymn family - admin.modifyColumnFamily(tableName, cfDescriptor).join(); - - HTableDescriptor htd = admin.getTableDescriptor(tableName).get(); - HColumnDescriptor hcfd = htd.getFamily(FAMILY_0); - assertTrue(hcfd.getBlocksize() == newBlockSize); - } finally { - admin.deleteTable(tableName).join(); - } - } - - @Test - public void testModifyNonExistingColumnFamily() throws IOException { - final TableName tableName = TableName.valueOf(name.getMethodName()); - - HColumnDescriptor cfDescriptor = new HColumnDescriptor(FAMILY_1); - int blockSize = cfDescriptor.getBlocksize(); - // Create a table with one families - HTableDescriptor baseHtd = new HTableDescriptor(tableName); - baseHtd.addFamily(new HColumnDescriptor(FAMILY_0)); - admin.createTable(baseHtd).join(); - admin.disableTable(tableName).join(); - try { - // Verify the table descriptor - verifyTableDescriptor(tableName, FAMILY_0); - - int newBlockSize = 2 * blockSize; - cfDescriptor.setBlocksize(newBlockSize); - - // Modify a column family that is not in the table. - try { - admin.modifyColumnFamily(tableName, cfDescriptor).join(); - Assert.fail("Modify a non-exist column family should fail"); - } catch (Exception e) { - // Expected. - } - } finally { - admin.deleteTable(tableName).join(); - } - } - - @Test - public void testDeleteColumnFamily() throws IOException { - final TableName tableName = TableName.valueOf(name.getMethodName()); - // Create a table with two families - HTableDescriptor baseHtd = new HTableDescriptor(tableName); - baseHtd.addFamily(new HColumnDescriptor(FAMILY_0)); - baseHtd.addFamily(new HColumnDescriptor(FAMILY_1)); - admin.createTable(baseHtd).join(); - admin.disableTable(tableName).join(); - try { - // Verify the table descriptor - verifyTableDescriptor(tableName, FAMILY_0, FAMILY_1); - - // Modify the table removing one family and verify the descriptor - admin.deleteColumnFamily(tableName, FAMILY_1).join(); - verifyTableDescriptor(tableName, FAMILY_0); - } finally { - admin.deleteTable(tableName).join(); - } - } - - @Test - public void testDeleteSameColumnFamilyTwice() throws IOException { - final TableName tableName = TableName.valueOf(name.getMethodName()); - // Create a table with two families - HTableDescriptor baseHtd = new HTableDescriptor(tableName); - baseHtd.addFamily(new HColumnDescriptor(FAMILY_0)); - baseHtd.addFamily(new HColumnDescriptor(FAMILY_1)); - admin.createTable(baseHtd).join(); - admin.disableTable(tableName).join(); - try { - // Verify the table descriptor - verifyTableDescriptor(tableName, FAMILY_0, FAMILY_1); - - // Modify the table removing one family and verify the descriptor - admin.deleteColumnFamily(tableName, FAMILY_1).join(); - verifyTableDescriptor(tableName, FAMILY_0); - - try { - // Delete again - expect failure - admin.deleteColumnFamily(tableName, FAMILY_1).join(); - Assert.fail("Delete a non-exist column family should fail"); - } catch (Exception e) { - // Expected. - } - } finally { - admin.deleteTable(tableName).join(); - } - } - - private void verifyTableDescriptor(final TableName tableName, final byte[]... families) - throws IOException { - Admin admin = TEST_UTIL.getAdmin(); - - // Verify descriptor from master - HTableDescriptor htd = admin.getTableDescriptor(tableName); - verifyTableDescriptor(htd, tableName, families); - - // Verify descriptor from HDFS - MasterFileSystem mfs = TEST_UTIL.getMiniHBaseCluster().getMaster().getMasterFileSystem(); - Path tableDir = FSUtils.getTableDir(mfs.getRootDir(), tableName); - HTableDescriptor td = FSTableDescriptors - .getTableDescriptorFromFs(mfs.getFileSystem(), tableDir); - verifyTableDescriptor(td, tableName, families); - } - - private void verifyTableDescriptor(final HTableDescriptor htd, final TableName tableName, - final byte[]... families) { - Set<byte[]> htdFamilies = htd.getFamiliesKeys(); - assertEquals(tableName, htd.getTableName()); - assertEquals(families.length, htdFamilies.size()); - for (byte[] familyName : families) { - assertTrue("Expected family " + Bytes.toString(familyName), htdFamilies.contains(familyName)); - } - } - - @Test(timeout = 30000) - public void testBalancer() throws Exception { - boolean initialState = admin.isBalancerEnabled().get(); - - // Start the balancer, wait for it. - boolean prevState = admin.setBalancerRunning(!initialState).get(); - - // The previous state should be the original state we observed - assertEquals(initialState, prevState); - - // Current state should be opposite of the original - assertEquals(!initialState, admin.isBalancerEnabled().get()); - - // Reset it back to what it was - prevState = admin.setBalancerRunning(initialState).get(); - - // The previous state should be the opposite of the initial state - assertEquals(!initialState, prevState); - // Current state should be the original state again - assertEquals(initialState, admin.isBalancerEnabled().get()); - } - - private void createTableWithDefaultConf(TableName TABLENAME) throws Exception { - HTableDescriptor htd = new HTableDescriptor(TABLENAME); - HColumnDescriptor hcd = new HColumnDescriptor("value"); - htd.addFamily(hcd); - - admin.createTable(htd, null).get(); - } - - @Test - public void testCloseRegion() throws Exception { - TableName TABLENAME = TableName.valueOf("TestHBACloseRegion"); - createTableWithDefaultConf(TABLENAME); - - HRegionInfo info = null; - HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME); - List<HRegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()); - for (HRegionInfo regionInfo : onlineRegions) { - if (!regionInfo.getTable().isSystemTable()) { - info = regionInfo; - boolean closed = admin.closeRegionWithEncodedRegionName(regionInfo.getEncodedName(), - rs.getServerName().getServerName()).get(); - assertTrue(closed); - } - } - boolean isInList = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()).contains(info); - long timeout = System.currentTimeMillis() + 10000; - while ((System.currentTimeMillis() < timeout) && (isInList)) { - Thread.sleep(100); - isInList = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()).contains(info); - } - - assertFalse("The region should not be present in online regions list.", isInList); - } - - @Test - public void testCloseRegionIfInvalidRegionNameIsPassed() throws Exception { - final String name = "TestHBACloseRegion1"; - byte[] TABLENAME = Bytes.toBytes(name); - createTableWithDefaultConf(TableName.valueOf(TABLENAME)); - - HRegionInfo info = null; - HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TableName.valueOf(TABLENAME)); - List<HRegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()); - for (HRegionInfo regionInfo : onlineRegions) { - if (!regionInfo.isMetaTable()) { - if (regionInfo.getRegionNameAsString().contains(name)) { - info = regionInfo; - boolean catchNotServingException = false; - try { - admin.closeRegionWithEncodedRegionName("sample", rs.getServerName().getServerName()) - .get(); - } catch (Exception e) { - catchNotServingException = true; - // expected, ignore it - } - assertTrue(catchNotServingException); - } - } - } - onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()); - assertTrue("The region should be present in online regions list.", - onlineRegions.contains(info)); - } - - @Test - public void testCloseRegionThatFetchesTheHRIFromMeta() throws Exception { - TableName TABLENAME = TableName.valueOf("TestHBACloseRegion2"); - createTableWithDefaultConf(TABLENAME); - - HRegionInfo info = null; - HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TABLENAME); - List<HRegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()); - for (HRegionInfo regionInfo : onlineRegions) { - if (!regionInfo.isMetaTable()) { - - if (regionInfo.getRegionNameAsString().contains("TestHBACloseRegion2")) { - info = regionInfo; - admin.closeRegion(regionInfo.getRegionNameAsString(), rs.getServerName().getServerName()) - .get(); - } - } - } - - boolean isInList = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()).contains(info); - long timeout = System.currentTimeMillis() + 10000; - while ((System.currentTimeMillis() < timeout) && (isInList)) { - Thread.sleep(100); - isInList = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()).contains(info); - } - - assertFalse("The region should not be present in online regions list.", isInList); - } - - @Test - public void testCloseRegionWhenServerNameIsNull() throws Exception { - byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion3"); - createTableWithDefaultConf(TableName.valueOf(TABLENAME)); - - HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TableName.valueOf(TABLENAME)); - - try { - List<HRegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()); - for (HRegionInfo regionInfo : onlineRegions) { - if (!regionInfo.isMetaTable()) { - if (regionInfo.getRegionNameAsString().contains("TestHBACloseRegion3")) { - admin.closeRegionWithEncodedRegionName(regionInfo.getEncodedName(), null).get(); - } - } - } - fail("The test should throw exception if the servername passed is null."); - } catch (IllegalArgumentException e) { - } - } - - @Test - public void testCloseRegionWhenServerNameIsEmpty() throws Exception { - byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegionWhenServerNameIsEmpty"); - createTableWithDefaultConf(TableName.valueOf(TABLENAME)); - - HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TableName.valueOf(TABLENAME)); - - try { - List<HRegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()); - for (HRegionInfo regionInfo : onlineRegions) { - if (!regionInfo.isMetaTable()) { - if (regionInfo.getRegionNameAsString() - .contains("TestHBACloseRegionWhenServerNameIsEmpty")) { - admin.closeRegionWithEncodedRegionName(regionInfo.getEncodedName(), " ").get(); - } - } - } - fail("The test should throw exception if the servername passed is empty."); - } catch (IllegalArgumentException e) { - } - } - - @Test - public void testCloseRegionWhenEncodedRegionNameIsNotGiven() throws Exception { - byte[] TABLENAME = Bytes.toBytes("TestHBACloseRegion4"); - createTableWithDefaultConf(TableName.valueOf(TABLENAME)); - - HRegionInfo info = null; - HRegionServer rs = TEST_UTIL.getRSForFirstRegionInTable(TableName.valueOf(TABLENAME)); - - List<HRegionInfo> onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()); - for (HRegionInfo regionInfo : onlineRegions) { - if (!regionInfo.isMetaTable()) { - if (regionInfo.getRegionNameAsString().contains("TestHBACloseRegion4")) { - info = regionInfo; - boolean catchNotServingException = false; - try { - admin.closeRegionWithEncodedRegionName(regionInfo.getRegionNameAsString(), - rs.getServerName().getServerName()).get(); - } catch (Exception e) { - // expected, ignore it. - catchNotServingException = true; - } - assertTrue(catchNotServingException); - } - } - } - onlineRegions = ProtobufUtil.getOnlineRegions(rs.getRSRpcServices()); - assertTrue("The region should be present in online regions list.", - onlineRegions.contains(info)); - } - - @Test - public void testGetRegion() throws Exception { - AsyncHBaseAdmin rawAdmin = (AsyncHBaseAdmin) admin; - - final TableName tableName = TableName.valueOf("testGetRegion"); - LOG.info("Started " + tableName); - TEST_UTIL.createMultiRegionTable(tableName, HConstants.CATALOG_FAMILY); - - try (RegionLocator locator = TEST_UTIL.getConnection().getRegionLocator(tableName)) { - HRegionLocation regionLocation = locator.getRegionLocation(Bytes.toBytes("mmm")); - HRegionInfo region = regionLocation.getRegionInfo(); - byte[] regionName = region.getRegionName(); - Pair<HRegionInfo, ServerName> pair = rawAdmin.getRegion(regionName).get(); - assertTrue(Bytes.equals(regionName, pair.getFirst().getRegionName())); - pair = rawAdmin.getRegion(region.getEncodedNameAsBytes()).get(); - assertTrue(Bytes.equals(regionName, pair.getFirst().getRegionName())); - } - } -} http://git-wip-us.apache.org/repos/asf/hbase/blob/4ff838df/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAdminBase.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAdminBase.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAdminBase.java new file mode 100644 index 0000000..583ec64 --- /dev/null +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncAdminBase.java @@ -0,0 +1,67 @@ +/** + * 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 static org.apache.hadoop.hbase.client.AsyncProcess.START_LOG_ERRORS_AFTER_COUNT_KEY; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.hbase.HBaseTestingUtility; +import org.apache.hadoop.hbase.HConstants; +import org.apache.hadoop.hbase.util.Bytes; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; + +/** + * Class to test AsyncAdmin. + */ +public abstract class TestAsyncAdminBase { + + protected static final Log LOG = LogFactory.getLog(TestAdmin1.class); + protected final static HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility(); + protected static byte[] FAMILY = Bytes.toBytes("testFamily"); + protected static final byte[] FAMILY_0 = Bytes.toBytes("cf0"); + protected static final byte[] FAMILY_1 = Bytes.toBytes("cf1"); + + protected static AsyncConnection ASYNC_CONN; + protected AsyncAdmin admin; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_PAUSE, 10); + TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER, 3); + TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_RPC_TIMEOUT_KEY, 1000); + TEST_UTIL.getConfiguration().setInt(HConstants.HBASE_CLIENT_OPERATION_TIMEOUT, 3000); + TEST_UTIL.getConfiguration().setInt(START_LOG_ERRORS_AFTER_COUNT_KEY, 0); + TEST_UTIL.startMiniCluster(1); + ASYNC_CONN = ConnectionFactory.createAsyncConnection(TEST_UTIL.getConfiguration()).get(); + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + IOUtils.closeQuietly(ASYNC_CONN); + TEST_UTIL.shutdownMiniCluster(); + } + + @Before + public void setUp() throws Exception { + this.admin = ASYNC_CONN.getAdmin(); + } +} http://git-wip-us.apache.org/repos/asf/hbase/blob/4ff838df/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncBalancerAdminApi.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncBalancerAdminApi.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncBalancerAdminApi.java new file mode 100644 index 0000000..b1df40e --- /dev/null +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncBalancerAdminApi.java @@ -0,0 +1,51 @@ +/** + * 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 static org.junit.Assert.assertEquals; + +import org.apache.hadoop.hbase.testclassification.ClientTests; +import org.apache.hadoop.hbase.testclassification.MediumTests; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +@Category({ MediumTests.class, ClientTests.class }) +public class TestAsyncBalancerAdminApi extends TestAsyncAdminBase { + + @Test + public void testBalancer() throws Exception { + boolean initialState = admin.isBalancerEnabled().get(); + + // Start the balancer, wait for it. + boolean prevState = admin.setBalancerRunning(!initialState).get(); + + // The previous state should be the original state we observed + assertEquals(initialState, prevState); + + // Current state should be opposite of the original + assertEquals(!initialState, admin.isBalancerEnabled().get()); + + // Reset it back to what it was + prevState = admin.setBalancerRunning(initialState).get(); + + // The previous state should be the opposite of the initial state + assertEquals(!initialState, prevState); + // Current state should be the original state again + assertEquals(initialState, admin.isBalancerEnabled().get()); + } +} http://git-wip-us.apache.org/repos/asf/hbase/blob/4ff838df/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncNamespaceAdminApi.java ---------------------------------------------------------------------- diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncNamespaceAdminApi.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncNamespaceAdminApi.java new file mode 100644 index 0000000..5cab420 --- /dev/null +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/client/TestAsyncNamespaceAdminApi.java @@ -0,0 +1,189 @@ +/** + * 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 static org.apache.hadoop.hbase.client.AsyncProcess.START_LOG_ERRORS_AFTER_COUNT_KEY; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.concurrent.Callable; + +import org.apache.hadoop.hbase.HColumnDescriptor; +import org.apache.hadoop.hbase.HTableDescriptor; +import org.apache.hadoop.hbase.MiniHBaseCluster; +import org.apache.hadoop.hbase.NamespaceDescriptor; +import org.apache.hadoop.hbase.NamespaceExistException; +import org.apache.hadoop.hbase.NamespaceNotFoundException; +import org.apache.hadoop.hbase.TableName; +import org.apache.hadoop.hbase.Waiter; +import org.apache.hadoop.hbase.ZKNamespaceManager; +import org.apache.hadoop.hbase.master.HMaster; +import org.apache.hadoop.hbase.testclassification.ClientTests; +import org.apache.hadoop.hbase.testclassification.MediumTests; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +/** + * Class to test asynchronous namespace admin operations. + */ +@Category({ MediumTests.class, ClientTests.class }) +public class TestAsyncNamespaceAdminApi extends TestAsyncAdminBase { + + private String prefix = "TestNamespace"; + private static HMaster master; + private static ZKNamespaceManager zkNamespaceManager; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + TEST_UTIL.getConfiguration().setInt(START_LOG_ERRORS_AFTER_COUNT_KEY, 0); + TEST_UTIL.startMiniCluster(1); + ASYNC_CONN = ConnectionFactory.createAsyncConnection(TEST_UTIL.getConfiguration()).get(); + master = ((MiniHBaseCluster) TEST_UTIL.getHBaseCluster()).getMaster(); + zkNamespaceManager = new ZKNamespaceManager(master.getZooKeeper()); + zkNamespaceManager.start(); + LOG.info("Done initializing cluster"); + } + + @Test(timeout = 60000) + public void testCreateAndDelete() throws Exception { + String testName = "testCreateAndDelete"; + String nsName = prefix + "_" + testName; + + // create namespace and verify + admin.createNamespace(NamespaceDescriptor.create(nsName).build()).join(); + assertEquals(3, admin.listNamespaceDescriptors().get().length); + TEST_UTIL.waitFor(60000, new Waiter.Predicate<Exception>() { + @Override + public boolean evaluate() throws Exception { + return zkNamespaceManager.list().size() == 3; + } + }); + assertNotNull(zkNamespaceManager.get(nsName)); + // delete namespace and verify + admin.deleteNamespace(nsName).join(); + assertEquals(2, admin.listNamespaceDescriptors().get().length); + assertEquals(2, zkNamespaceManager.list().size()); + assertNull(zkNamespaceManager.get(nsName)); + } + + @Test(timeout = 60000) + public void testDeleteReservedNS() throws Exception { + boolean exceptionCaught = false; + try { + admin.deleteNamespace(NamespaceDescriptor.DEFAULT_NAMESPACE_NAME_STR).join(); + } catch (Exception exp) { + LOG.warn(exp); + exceptionCaught = true; + } finally { + assertTrue(exceptionCaught); + } + + try { + admin.deleteNamespace(NamespaceDescriptor.SYSTEM_NAMESPACE_NAME_STR).join(); + } catch (Exception exp) { + LOG.warn(exp); + exceptionCaught = true; + } finally { + assertTrue(exceptionCaught); + } + } + + @Test(timeout = 60000) + public void testNamespaceOperations() throws Exception { + admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()).join(); + admin.createNamespace(NamespaceDescriptor.create(prefix + "ns2").build()).join(); + + // create namespace that already exists + runWithExpectedException(new Callable<Void>() { + @Override + public Void call() throws Exception { + admin.createNamespace(NamespaceDescriptor.create(prefix + "ns1").build()).join(); + return null; + } + }, NamespaceExistException.class); + + // create a table in non-existing namespace + runWithExpectedException(new Callable<Void>() { + @Override + public Void call() throws Exception { + HTableDescriptor htd = new HTableDescriptor(TableName.valueOf("non_existing_namespace", + "table1")); + htd.addFamily(new HColumnDescriptor("family1")); + admin.createTable(htd).join(); + return null; + } + }, NamespaceNotFoundException.class); + + // get descriptor for existing namespace + NamespaceDescriptor ns1 = admin.getNamespaceDescriptor(prefix + "ns1").get(); + assertEquals(prefix + "ns1", ns1.getName()); + + // get descriptor for non-existing namespace + runWithExpectedException(new Callable<NamespaceDescriptor>() { + @Override + public NamespaceDescriptor call() throws Exception { + return admin.getNamespaceDescriptor("non_existing_namespace").get(); + } + }, NamespaceNotFoundException.class); + + // delete descriptor for existing namespace + admin.deleteNamespace(prefix + "ns2").join(); + + // delete descriptor for non-existing namespace + runWithExpectedException(new Callable<Void>() { + @Override + public Void call() throws Exception { + admin.deleteNamespace("non_existing_namespace").join(); + return null; + } + }, NamespaceNotFoundException.class); + + // modify namespace descriptor for existing namespace + ns1 = admin.getNamespaceDescriptor(prefix + "ns1").get(); + ns1.setConfiguration("foo", "bar"); + admin.modifyNamespace(ns1).join(); + ns1 = admin.getNamespaceDescriptor(prefix + "ns1").get(); + assertEquals("bar", ns1.getConfigurationValue("foo")); + + // modify namespace descriptor for non-existing namespace + runWithExpectedException(new Callable<Void>() { + @Override + public Void call() throws Exception { + admin.modifyNamespace(NamespaceDescriptor.create("non_existing_namespace").build()).join(); + return null; + } + }, NamespaceNotFoundException.class); + + admin.deleteNamespace(prefix + "ns1").join(); + } + + private static <V, E> void runWithExpectedException(Callable<V> callable, Class<E> exceptionClass) { + try { + callable.call(); + } catch (Exception ex) { + LOG.info("Get exception is " + ex); + assertEquals(exceptionClass, ex.getCause().getClass()); + return; + } + fail("Should have thrown exception " + exceptionClass); + } +}