From 5ee90978b887ab4174e21e7b939b948e2bc135c4 Mon Sep 17 00:00:00 2001 From: Sakthi Date: Tue, 18 Dec 2018 02:07:00 -0800 Subject: [PATCH] HBASE-21225: Having RPC & Space quota on a table/Namespace doesn't allow space quota to be removed using 'NONE' Removed the 'remove' attribute from the SpaceQuota protobuf. --- .../hadoop/hbase/quotas/QuotaSettings.java | 8 +- .../hbase/quotas/QuotaSettingsFactory.java | 45 ++++-- .../hbase/quotas/SpaceLimitSettings.java | 145 ++++-------------- .../quotas/TestQuotaSettingsFactory.java | 9 +- .../src/main/protobuf/Quota.proto | 1 - hbase-protocol/src/main/protobuf/Quota.proto | 1 - .../hbase/quotas/GlobalQuotaSettingsImpl.java | 41 ++--- .../quotas/TestMasterQuotasObserver.java | 122 ++++++++++++++- 8 files changed, 195 insertions(+), 177 deletions(-) diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaSettings.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaSettings.java index 3351a25038bbf6a69fe7886176f1c95fc5181a75..586c52a6d375698937185f9f70766fbe12b603ef 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaSettings.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaSettings.java @@ -92,13 +92,7 @@ public abstract class QuotaSettings { throw new IllegalStateException( "SetQuotaRequests has multiple limits: " + TextFormat.shortDebugString(request)); } - // Sanity check on the pb received. - if (!request.getSpaceLimit().hasQuota()) { - throw new IllegalArgumentException( - "SpaceLimitRequest is missing the expected SpaceQuota."); - } - return QuotaSettingsFactory.fromSpace( - tableName, namespace, request.getSpaceLimit().getQuota()); + return new SpaceLimitSettings(tableName, namespace, request.getSpaceLimit()); } else if (request.hasThrottle()) { return new ThrottleSettings(username, tableName, namespace, request.getThrottle()); } else { diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaSettingsFactory.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaSettingsFactory.java index 14d1ad31b3ddc2b79b7a1d5ce92601a2e3a0302b..1d4bff4439522aff817ccd215da7b5541b75d782 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaSettingsFactory.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaSettingsFactory.java @@ -166,18 +166,20 @@ public class QuotaSettingsFactory { throw new IllegalArgumentException( "Can only construct SpaceLimitSettings for a table or namespace."); } - if (table != null) { - if (protoQuota.getRemove()) { - return new SpaceLimitSettings(table); + QuotaProtos.SpaceLimitRequest.Builder builder = QuotaProtos.SpaceLimitRequest.newBuilder(); + + if(protoQuota.hasViolationPolicy()){ + if (!protoQuota.hasSoftLimit()) { + throw new IllegalArgumentException( + "Space Quota Size Limit is not set while Violation Policy is set"); } - return SpaceLimitSettings.fromSpaceQuota(table, protoQuota); - } else { - if (protoQuota.getRemove()) { - return new SpaceLimitSettings(namespace); + if(protoQuota.getSoftLimit() < 0L) { + throw new IllegalArgumentException("Size limit must be a non-negative value."); } - // namespace must be non-null - return SpaceLimitSettings.fromSpaceQuota(namespace, protoQuota); + builder.setQuota(SpaceQuota.newBuilder().setSoftLimit(protoQuota.getSoftLimit()) + .setViolationPolicy(protoQuota.getViolationPolicy()).build()); } + return new SpaceLimitSettings(table, namespace, builder.build()); } /* ========================================================================== @@ -353,7 +355,7 @@ public class QuotaSettingsFactory { */ public static QuotaSettings limitTableSpace( final TableName tableName, long sizeLimit, final SpaceViolationPolicy violationPolicy) { - return new SpaceLimitSettings(tableName, sizeLimit, violationPolicy); + return limitSpace(tableName, null, sizeLimit, violationPolicy); } /** @@ -364,7 +366,7 @@ public class QuotaSettingsFactory { * @return A {@link QuotaSettings} object. */ public static QuotaSettings removeTableSpaceLimit(TableName tableName) { - return new SpaceLimitSettings(tableName); + return limitSpace(tableName,null,0,null); } /** @@ -379,7 +381,7 @@ public class QuotaSettingsFactory { */ public static QuotaSettings limitNamespaceSpace( final String namespace, long sizeLimit, final SpaceViolationPolicy violationPolicy) { - return new SpaceLimitSettings(namespace, sizeLimit, violationPolicy); + return limitSpace(null, namespace, sizeLimit, violationPolicy); } /** @@ -390,6 +392,21 @@ public class QuotaSettingsFactory { * @return A {@link QuotaSettings} object. */ public static QuotaSettings removeNamespaceSpaceLimit(String namespace) { - return new SpaceLimitSettings(namespace); + return limitSpace(null, namespace, 0, null); + } + + /* Space Quota Helper */ + private static QuotaSettings limitSpace(final TableName tableName, final String nameSpace, + long sizeLimit, final SpaceViolationPolicy violationPolicy) { + QuotaProtos.SpaceLimitRequest.Builder builder = QuotaProtos.SpaceLimitRequest.newBuilder(); + if (sizeLimit < 0L) { + throw new IllegalArgumentException("Size limit must be a non-negative value."); + } + if (violationPolicy != null) { + builder.setQuota(SpaceQuota.newBuilder().setSoftLimit(sizeLimit) + .setViolationPolicy(ProtobufUtil.toProtoViolationPolicy(violationPolicy)).build()); + } + + return new SpaceLimitSettings(tableName, nameSpace, builder.build()); } -} +} \ No newline at end of file diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/SpaceLimitSettings.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/SpaceLimitSettings.java index 02bd6e489e8ba4e349461be68fcdc4fc6730de0f..09ade71bff6e0d6f64774bd81f95c162f3e30a5c 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/SpaceLimitSettings.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/SpaceLimitSettings.java @@ -36,41 +36,29 @@ class SpaceLimitSettings extends QuotaSettings { private final SpaceLimitRequest proto; - SpaceLimitSettings(TableName tableName, long sizeLimit, SpaceViolationPolicy violationPolicy) { - super(null, Objects.requireNonNull(tableName), null); - if (sizeLimit < 0L) { - throw new IllegalArgumentException("Size limit must be a non-negative value."); - } - proto = buildProtoAddQuota(sizeLimit, Objects.requireNonNull(violationPolicy)); + SpaceLimitSettings(TableName tableName, String namespace, SpaceLimitRequest req) { + super(null, tableName, namespace); + proto = req; } - /** - * Constructs a {@code SpaceLimitSettings} to remove a space quota on the given {@code tableName}. - */ - SpaceLimitSettings(TableName tableName) { + SpaceLimitSettings(TableName tableName, long sizeLimit, SpaceViolationPolicy violationPolicy){ super(null, Objects.requireNonNull(tableName), null); - proto = buildProtoRemoveQuota(); + proto = createSpaceLimitRequest(sizeLimit, Objects.requireNonNull(violationPolicy)); } - SpaceLimitSettings(String namespace, long sizeLimit, SpaceViolationPolicy violationPolicy) { + SpaceLimitSettings(String namespace, long sizeLimit, SpaceViolationPolicy violationPolicy){ super(null, null, Objects.requireNonNull(namespace)); + proto = createSpaceLimitRequest(sizeLimit, Objects.requireNonNull(violationPolicy)); + } + + public SpaceLimitRequest createSpaceLimitRequest(long sizeLimit, SpaceViolationPolicy violationPolicy){ + QuotaProtos.SpaceLimitRequest.Builder builder = QuotaProtos.SpaceLimitRequest.newBuilder(); if (sizeLimit < 0L) { throw new IllegalArgumentException("Size limit must be a non-negative value."); } - proto = buildProtoAddQuota(sizeLimit, Objects.requireNonNull(violationPolicy)); - } - - /** - * Constructs a {@code SpaceLimitSettings} to remove a space quota on the given {@code namespace}. - */ - SpaceLimitSettings(String namespace) { - super(null, null, Objects.requireNonNull(namespace)); - proto = buildProtoRemoveQuota(); - } - - SpaceLimitSettings(TableName tableName, String namespace, SpaceLimitRequest req) { - super(null, tableName, namespace); - proto = req; + builder.setQuota(SpaceQuota.newBuilder().setSoftLimit(sizeLimit) + .setViolationPolicy(ProtobufUtil.toProtoViolationPolicy(violationPolicy)).build()); + return builder.build(); } /** @@ -83,34 +71,6 @@ class SpaceLimitSettings extends QuotaSettings { return SpaceLimitRequest.newBuilder().setQuota(protoQuota).build(); } - /** - * Builds a {@link SpaceQuota} protobuf object given the arguments. - * - * @param sizeLimit The size limit of the quota. - * @param violationPolicy The action to take when the quota is exceeded. - * @return The protobuf SpaceQuota representation. - */ - private SpaceLimitRequest buildProtoAddQuota( - long sizeLimit, SpaceViolationPolicy violationPolicy) { - return buildProtoFromQuota(SpaceQuota.newBuilder() - .setSoftLimit(sizeLimit) - .setViolationPolicy(ProtobufUtil.toProtoViolationPolicy(violationPolicy)) - .build()); - } - - /** - * Builds a {@link SpaceQuota} protobuf object to remove a quota. - * - * @return The protobuf SpaceQuota representation. - */ - private SpaceLimitRequest buildProtoRemoveQuota() { - return SpaceLimitRequest.newBuilder().setQuota( - SpaceQuota.newBuilder() - .setRemove(true) - .build()) - .build(); - } - /** * Returns a copy of the internal state of this */ @@ -129,49 +89,6 @@ class SpaceLimitSettings extends QuotaSettings { builder.setSpaceLimit(proto); } - /** - * Constructs a {@link SpaceLimitSettings} from the provided protobuf message and tablename. - * - * @param tableName The target tablename for the limit. - * @param proto The protobuf representation. - * @return A QuotaSettings. - */ - static SpaceLimitSettings fromSpaceQuota( - final TableName tableName, final QuotaProtos.SpaceQuota proto) { - validateProtoArguments(proto); - return new SpaceLimitSettings(tableName, proto.getSoftLimit(), - ProtobufUtil.toViolationPolicy(proto.getViolationPolicy())); - } - - /** - * Constructs a {@link SpaceLimitSettings} from the provided protobuf message and namespace. - * - * @param namespace The target namespace for the limit. - * @param proto The protobuf representation. - * @return A QuotaSettings. - */ - static SpaceLimitSettings fromSpaceQuota( - final String namespace, final QuotaProtos.SpaceQuota proto) { - validateProtoArguments(proto); - return new SpaceLimitSettings(namespace, proto.getSoftLimit(), - ProtobufUtil.toViolationPolicy(proto.getViolationPolicy())); - } - - /** - * Validates that the provided protobuf SpaceQuota has the necessary information to construct - * a {@link SpaceLimitSettings}. - * - * @param proto The protobuf message to validate. - */ - static void validateProtoArguments(final QuotaProtos.SpaceQuota proto) { - if (!Objects.requireNonNull(proto).hasSoftLimit()) { - throw new IllegalArgumentException("Cannot handle SpaceQuota without a soft limit"); - } - if (!proto.hasViolationPolicy()) { - throw new IllegalArgumentException("Cannot handle SpaceQuota without a violation policy"); - } - } - @Override public int hashCode() { return Objects.hash(getTableName(), getNamespace(), proto); @@ -202,8 +119,8 @@ class SpaceLimitSettings extends QuotaSettings { if (getNamespace() != null) { sb.append(", NAMESPACE => ").append(getNamespace()); } - if (proto.getQuota().getRemove()) { - sb.append(", REMOVE => ").append(proto.getQuota().getRemove()); + if (!proto.hasQuota()) { + sb.append(", LIMIT => NONE"); } else { sb.append(", LIMIT => ").append(proto.getQuota().getSoftLimit()); sb.append(", VIOLATION_POLICY => ").append(proto.getQuota().getViolationPolicy()); @@ -219,25 +136,21 @@ class SpaceLimitSettings extends QuotaSettings { // The message contained the expect SpaceQuota object if (settingsToMerge.proto.hasQuota()) { SpaceQuota quotaToMerge = settingsToMerge.proto.getQuota(); - if (quotaToMerge.getRemove()) { - return settingsToMerge; - } else { - // Validate that the two settings are for the same target. - // SpaceQuotas either apply to a table or a namespace (no user spacequota). - if (!Objects.equals(getTableName(), settingsToMerge.getTableName()) - && !Objects.equals(getNamespace(), settingsToMerge.getNamespace())) { - throw new IllegalArgumentException("Cannot merge " + newSettings + " into " + this); - } - // Create a builder from the old settings - SpaceQuota.Builder mergedBuilder = this.proto.getQuota().toBuilder(); - // Build a new SpaceQuotas object from merging in the new settings - return new SpaceLimitSettings( - getTableName(), getNamespace(), - buildProtoFromQuota(mergedBuilder.mergeFrom(quotaToMerge).build())); + + // Validate that the two settings are for the same target. + // SpaceQuotas either apply to a table or a namespace (no user spacequota). + if (!Objects.equals(getTableName(), settingsToMerge.getTableName()) && !Objects + .equals(getNamespace(), settingsToMerge.getNamespace())) { + throw new IllegalArgumentException("Cannot merge " + newSettings + " into " + this); } + // Create a builder from the old settings + SpaceQuota.Builder mergedBuilder = this.proto.getQuota().toBuilder(); + // Build a new SpaceQuotas object from merging in the new settings + return new SpaceLimitSettings(getTableName(), getNamespace(), + buildProtoFromQuota(mergedBuilder.mergeFrom(quotaToMerge).build())); } - // else, we don't know what to do, so return the original object + return settingsToMerge; } return this; } -} +} \ No newline at end of file diff --git a/hbase-client/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaSettingsFactory.java b/hbase-client/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaSettingsFactory.java index 2f1942c5be2e8b90e604e2fdad1b851ee249faf1..ccfc548a4e79512c4c6978216fa8da23038ef7eb 100644 --- a/hbase-client/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaSettingsFactory.java +++ b/hbase-client/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaSettingsFactory.java @@ -151,7 +151,6 @@ public class TestQuotaSettingsFactory { SpaceQuota quota = protoRequest.getQuota(); assertEquals(sizeLimit, quota.getSoftLimit()); assertEquals(violationPolicy, ProtobufUtil.toViolationPolicy(quota.getViolationPolicy())); - assertFalse("The remove attribute should be false", quota.getRemove()); } @Test @@ -162,14 +161,14 @@ public class TestQuotaSettingsFactory { assertNotNull("QuotaSettings should not be null", nsSettings); assertTrue("Should be an instance of SpaceLimitSettings", nsSettings instanceof SpaceLimitSettings); SpaceLimitRequest nsProto = ((SpaceLimitSettings) nsSettings).getProto(); - assertTrue("Request should have a SpaceQuota", nsProto.hasQuota()); - assertTrue("The remove attribute should be true", nsProto.getQuota().getRemove()); + // To make sure that it's a remove quota setting + assertTrue("Request should not have a SpaceQuota", !nsProto.hasQuota()); QuotaSettings tableSettings = QuotaSettingsFactory.removeTableSpaceLimit(tn); assertNotNull("QuotaSettings should not be null", tableSettings); assertTrue("Should be an instance of SpaceLimitSettings", tableSettings instanceof SpaceLimitSettings); SpaceLimitRequest tableProto = ((SpaceLimitSettings) tableSettings).getProto(); - assertTrue("Request should have a SpaceQuota", tableProto.hasQuota()); - assertTrue("The remove attribute should be true", tableProto.getQuota().getRemove()); + // To make sure that it's a remove quota setting + assertTrue("Request should not have a SpaceQuota", !tableProto.hasQuota()); } } diff --git a/hbase-protocol-shaded/src/main/protobuf/Quota.proto b/hbase-protocol-shaded/src/main/protobuf/Quota.proto index 5b00d74980b5b368f26baf7c2260000763343a4d..6dd51a60bad33189f87de117f1fdcf35f1e4266c 100644 --- a/hbase-protocol-shaded/src/main/protobuf/Quota.proto +++ b/hbase-protocol-shaded/src/main/protobuf/Quota.proto @@ -97,7 +97,6 @@ enum SpaceViolationPolicy { message SpaceQuota { optional uint64 soft_limit = 1; // The limit of bytes for this quota optional SpaceViolationPolicy violation_policy = 2; // The action to take when the quota is violated - optional bool remove = 3 [default = false]; // When true, remove the quota. } // The Request to limit space usage (to allow for schema evolution not tied to SpaceQuota). diff --git a/hbase-protocol/src/main/protobuf/Quota.proto b/hbase-protocol/src/main/protobuf/Quota.proto index 8e5c17ccf8d05e8f85997bd55aa54997fd220d35..2b2718c3f26865a46af36b10e49cc3068394cb3a 100644 --- a/hbase-protocol/src/main/protobuf/Quota.proto +++ b/hbase-protocol/src/main/protobuf/Quota.proto @@ -89,7 +89,6 @@ enum SpaceViolationPolicy { message SpaceQuota { optional uint64 soft_limit = 1; // The limit of bytes for this quota optional SpaceViolationPolicy violation_policy = 2; // The action to take when the quota is violated - optional bool remove = 3 [default = false]; // When true, remove the quota. } // The Request to limit space usage (to allow for schema evolution not tied to SpaceQuota). diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/GlobalQuotaSettingsImpl.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/GlobalQuotaSettingsImpl.java index 0c6cb81b8fcbc2b292b06301919b5ac8ff24e8d4..641cfe41b9b284320b1c799183a98b53361c6d45 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/GlobalQuotaSettingsImpl.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/GlobalQuotaSettingsImpl.java @@ -121,6 +121,7 @@ public class GlobalQuotaSettingsImpl extends GlobalQuotaSettings { if (other instanceof ThrottleSettings) { ThrottleSettings otherThrottle = (ThrottleSettings) other; if (!otherThrottle.proto.hasType() || !otherThrottle.proto.hasTimedQuota()) { + // It's a remove request // To prevent the "empty" row in QuotaTableUtil.QUOTA_TABLE_NAME throttleBuilder = null; } else { @@ -184,14 +185,11 @@ public class GlobalQuotaSettingsImpl extends GlobalQuotaSettings { throw new IllegalArgumentException( "Cannot merge " + settingsToMerge + " into " + this); } - - if (quotaToMerge.getRemove()) { - // Update the builder to propagate the removal - spaceBuilder.setRemove(true).clearSoftLimit().clearViolationPolicy(); - } else { - // Add the new settings to the existing settings - spaceBuilder.mergeFrom(quotaToMerge); - } + // Add the new settings to the existing settings + spaceBuilder.mergeFrom(quotaToMerge); + } else { + // Its a remove request + spaceBuilder = null; } } @@ -200,9 +198,7 @@ public class GlobalQuotaSettingsImpl extends GlobalQuotaSettings { bypassGlobals = ((QuotaGlobalsSettingsBypass) other).getBypass(); } - if (throttleBuilder == null && - (spaceBuilder == null || (spaceBuilder.hasRemove() && spaceBuilder.getRemove())) - && bypassGlobals == null) { + if (throttleBuilder == null && spaceBuilder == null && bypassGlobals == null) { return null; } @@ -273,13 +269,12 @@ public class GlobalQuotaSettingsImpl extends GlobalQuotaSettings { if (getNamespace() != null) { builder.append(", NAMESPACE => ").append(getNamespace()); } - if (spaceProto.getRemove()) { - builder.append(", REMOVE => ").append(spaceProto.getRemove()); - } else { - builder.append(", LIMIT => ").append(spaceProto.getSoftLimit()); - builder.append(", VIOLATION_POLICY => ").append(spaceProto.getViolationPolicy()); - } + builder.append(", LIMIT => ").append(spaceProto.getSoftLimit()); + builder.append(", VIOLATION_POLICY => ").append(spaceProto.getViolationPolicy()); + builder.append(" } "); + } else { + builder.append(" {} "); } return builder.toString(); } @@ -315,16 +310,4 @@ public class GlobalQuotaSettingsImpl extends GlobalQuotaSettings { } return quotas; } - - private void clearThrottleBuilder(QuotaProtos.Throttle.Builder builder) { - builder.clearReadNum(); - builder.clearReadSize(); - builder.clearReqNum(); - builder.clearReqSize(); - builder.clearWriteNum(); - builder.clearWriteSize(); - builder.clearReadCapacityUnit(); - builder.clearReadCapacityUnit(); - builder.clearWriteCapacityUnit(); - } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestMasterQuotasObserver.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestMasterQuotasObserver.java index 92e1d9dd4fa2f9ff7d987d963ac133f495836fe4..2083fba46d9c0c6ed50356014bae409856746ad0 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestMasterQuotasObserver.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestMasterQuotasObserver.java @@ -89,6 +89,118 @@ public class TestMasterQuotasObserver { } } + @Test + public void testTableWithSpaceAndRPCQuota() throws Exception { + final Connection conn = TEST_UTIL.getConnection(); + final Admin admin = conn.getAdmin(); + final TableName tn = TableName.valueOf(testName.getMethodName()); + // Drop the table if it somehow exists + if (admin.tableExists(tn)) { + dropTable(admin, tn); + } + createTable(admin, tn); + assertEquals(0, getNumSpaceQuotas()); + assertEquals(0, getThrottleQuotas()); + + // Set Both quotas + QuotaSettings settings = QuotaSettingsFactory.limitTableSpace(tn, 1024L, SpaceViolationPolicy.NO_INSERTS); + admin.setQuota(settings); + + settings = QuotaSettingsFactory.throttleTable(tn, ThrottleType.REQUEST_SIZE, 2L, TimeUnit.HOURS); + admin.setQuota(settings); + + assertEquals(1, getNumSpaceQuotas()); + assertEquals(1, getThrottleQuotas()); + + // Remove Space quota + settings = QuotaSettingsFactory.removeTableSpaceLimit(tn); + admin.setQuota(settings); + assertEquals(0, getNumSpaceQuotas()); + assertEquals(1, getThrottleQuotas()); + + // Set back the space quota + settings = QuotaSettingsFactory.limitTableSpace(tn, 1024L, SpaceViolationPolicy.NO_INSERTS); + admin.setQuota(settings); + assertEquals(1, getNumSpaceQuotas()); + assertEquals(1, getThrottleQuotas()); + + // Remove the throttle quota + settings = QuotaSettingsFactory.unthrottleTable(tn); + admin.setQuota(settings); + assertEquals(1, getNumSpaceQuotas()); + assertEquals(0, getThrottleQuotas()); + + // Set back the throttle quota + settings = QuotaSettingsFactory.throttleTable(tn, ThrottleType.REQUEST_SIZE, 2L, TimeUnit.HOURS); + admin.setQuota(settings); + assertEquals(1, getNumSpaceQuotas()); + assertEquals(1, getThrottleQuotas()); + + // Drop the table and check that both the quotas have been dropped as well + dropTable(admin, tn); + + assertEquals(0, getNumSpaceQuotas()); + assertEquals(0, getThrottleQuotas()); + } + + @Test + public void testNamespaceWithSpaceAndRPCQuota() throws Exception { + final Connection conn = TEST_UTIL.getConnection(); + final Admin admin = conn.getAdmin(); + final String ns = testName.getMethodName(); + // Drop the ns if it somehow exists + if (namespaceExists(ns)) { + admin.deleteNamespace(ns); + } + + // Create the ns + NamespaceDescriptor desc = NamespaceDescriptor.create(ns).build(); + admin.createNamespace(desc); + + assertEquals(0, getNumSpaceQuotas()); + assertEquals(0, getThrottleQuotas()); + + // Set Both quotas + QuotaSettings settings = QuotaSettingsFactory.limitNamespaceSpace(ns, 1024L, SpaceViolationPolicy.NO_INSERTS); + admin.setQuota(settings); + + settings = QuotaSettingsFactory.throttleNamespace(ns, ThrottleType.REQUEST_SIZE, 2L, TimeUnit.HOURS); + admin.setQuota(settings); + + assertEquals(1, getNumSpaceQuotas()); + assertEquals(1, getThrottleQuotas()); + + // Remove Space quota + settings = QuotaSettingsFactory.removeNamespaceSpaceLimit(ns); + admin.setQuota(settings); + assertEquals(0, getNumSpaceQuotas()); + assertEquals(1, getThrottleQuotas()); + + // Set back the space quota + settings = QuotaSettingsFactory.limitNamespaceSpace(ns, 1024L, SpaceViolationPolicy.NO_INSERTS); + admin.setQuota(settings); + assertEquals(1, getNumSpaceQuotas()); + assertEquals(1, getThrottleQuotas()); + + // Remove the throttle quota + settings = QuotaSettingsFactory.unthrottleNamespace(ns); + admin.setQuota(settings); + assertEquals(1, getNumSpaceQuotas()); + assertEquals(0, getThrottleQuotas()); + + // Set back the throttle quota + settings = QuotaSettingsFactory.throttleNamespace(ns, ThrottleType.REQUEST_SIZE, 2L, TimeUnit.HOURS); + admin.setQuota(settings); + assertEquals(1, getNumSpaceQuotas()); + assertEquals(1, getThrottleQuotas()); + + // Delete the namespace and check that both the quotas have been dropped as well + admin.deleteNamespace(ns); + + assertEquals(0, getNumSpaceQuotas()); + assertEquals(0, getThrottleQuotas()); + } + @Test public void testTableSpaceQuotaRemoved() throws Exception { final Connection conn = TEST_UTIL.getConnection(); @@ -98,16 +210,18 @@ public class TestMasterQuotasObserver { if (admin.tableExists(tn)) { dropTable(admin, tn); } + createTable(admin, tn); assertEquals(0, getNumSpaceQuotas()); - // Set space quota - QuotaSettings settings = QuotaSettingsFactory.limitTableSpace( - tn, 1024L, SpaceViolationPolicy.NO_INSERTS); + // Set Space quota + QuotaSettings settings = + QuotaSettingsFactory.limitTableSpace(tn, 1024L, SpaceViolationPolicy.NO_INSERTS); admin.setQuota(settings); + assertEquals(1, getNumSpaceQuotas()); - // Drop the table and observe the Space quota being automatically deleted as well + // Delete the table and observe the Space quota being automatically deleted as well dropTable(admin, tn); assertEquals(0, getNumSpaceQuotas()); } -- 2.17.2 (Apple Git-113)