From eed9d1aa16a434044aa95d373b6722f1771eae06 Mon Sep 17 00:00:00 2001 From: Josh Elser Date: Wed, 11 Jan 2017 12:47:06 -0500 Subject: [PATCH] HBASE-17259 API to remove space quotas on a table/namespace --- .../hadoop/hbase/quotas/QuotaSettingsFactory.java | 22 +++ .../apache/hadoop/hbase/quotas/QuotaTableUtil.java | 8 +- .../hadoop/hbase/quotas/SpaceLimitSettings.java | 44 ++++- .../hbase/quotas/TestQuotaSettingsFactory.java | 20 +++ .../shaded/protobuf/generated/QuotaProtos.java | 196 +++++++++++++++++---- .../src/main/protobuf/Quota.proto | 1 + .../hbase/protobuf/generated/QuotaProtos.java | 159 +++++++++++++++-- hbase-protocol/src/main/protobuf/Quota.proto | 1 + .../hadoop/hbase/quotas/MasterQuotaManager.java | 9 +- .../apache/hadoop/hbase/quotas/TestQuotaAdmin.java | 49 +++++- 10 files changed, 443 insertions(+), 66 deletions(-) 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 f436cf2..bedd318 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 @@ -318,6 +318,17 @@ public class QuotaSettingsFactory { } /** + * Creates a {@link QuotaSettings} object to remove the FileSystem space quota for the given + * table. + * + * @param tableName The name of the table to remove the quota for. + * @return A {@link QuotaSettings} object. + */ + public static QuotaSettings removeTableSpaceLimit(TableName tableName) { + return new SpaceLimitSettings(tableName, true); + } + + /** * Creates a {@link QuotaSettings} object to limit the FileSystem space usage for the given * namespace to the given size in bytes. When the space usage is exceeded by all tables in the * namespace, the provided {@link SpaceViolationPolicy} is enacted on all tables in the namespace. @@ -331,4 +342,15 @@ public class QuotaSettingsFactory { final String namespace, long sizeLimit, final SpaceViolationPolicy violationPolicy) { return new SpaceLimitSettings(namespace, sizeLimit, violationPolicy); } + + /** + * Creates a {@link QuotaSettings} object to remove the FileSystem space quota for the given + * namespace. + * + * @param namespace The namespace to remove the quota on. + * @return A {@link QuotaSettings} object. + */ + public static QuotaSettings removeNamespaceSpaceLimit(String namespace) { + return new SpaceLimitSettings(namespace, true); + } } diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaTableUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaTableUtil.java index e7b904e..f4573ac 100644 --- a/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaTableUtil.java +++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/quotas/QuotaTableUtil.java @@ -471,7 +471,11 @@ public class QuotaTableUtil { boolean hasSettings = false; hasSettings |= quotas.hasThrottle(); hasSettings |= quotas.hasBypassGlobals(); - hasSettings |= quotas.hasSpace(); + // Only when there is a space quota, make sure there's actually both fields provided + // Otherwise, it's a noop. + if (quotas.hasSpace()) { + hasSettings |= (quotas.getSpace().hasSoftLimit() && quotas.getSpace().hasViolationPolicy()); + } return !hasSettings; } @@ -578,4 +582,4 @@ public class QuotaTableUtil { } return ProtobufUtil.toViolationPolicy(proto.getViolationPolicy()); } -} \ 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 e54882e..8ff7623 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 @@ -41,7 +41,15 @@ class SpaceLimitSettings extends QuotaSettings { if (0L > sizeLimit) { throw new IllegalArgumentException("Size limit must be a non-negative value."); } - proto = buildProtoQuota(sizeLimit, Objects.requireNonNull(violationPolicy)); + proto = buildProtoAddQuota(sizeLimit, Objects.requireNonNull(violationPolicy)); + } + + SpaceLimitSettings(TableName tableName, boolean remove) { + super(null, Objects.requireNonNull(tableName), null); + if (!remove) { + throw new IllegalArgumentException("A value of 'false' for removing a quota makes no sense"); + } + proto = buildProtoRemoveQuota(); } SpaceLimitSettings(String namespace, long sizeLimit, SpaceViolationPolicy violationPolicy) { @@ -49,7 +57,15 @@ class SpaceLimitSettings extends QuotaSettings { if (0L > sizeLimit) { throw new IllegalArgumentException("Size limit must be a non-negative value."); } - proto = buildProtoQuota(sizeLimit, Objects.requireNonNull(violationPolicy)); + proto = buildProtoAddQuota(sizeLimit, Objects.requireNonNull(violationPolicy)); + } + + SpaceLimitSettings(String namespace, boolean remove) { + super(null, null, Objects.requireNonNull(namespace)); + if (!remove) { + throw new IllegalArgumentException("A value of 'false' for removing a quota makes no sense"); + } + proto = buildProtoRemoveQuota(); } /** @@ -59,7 +75,8 @@ class SpaceLimitSettings extends QuotaSettings { * @param violationPolicy The action to take when the quota is exceeded. * @return The protobuf SpaceQuota representation. */ - private SpaceLimitRequest buildProtoQuota(long sizeLimit, SpaceViolationPolicy violationPolicy) { + private SpaceLimitRequest buildProtoAddQuota( + long sizeLimit, SpaceViolationPolicy violationPolicy) { return SpaceLimitRequest.newBuilder().setQuota( SpaceQuota.newBuilder() .setSoftLimit(sizeLimit) @@ -69,6 +86,19 @@ class SpaceLimitSettings extends QuotaSettings { } /** + * 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 */ SpaceLimitRequest getProto() { @@ -159,8 +189,12 @@ class SpaceLimitSettings extends QuotaSettings { if (null != getNamespace()) { sb.append(", NAMESPACE => ").append(getNamespace()); } - sb.append(", LIMIT => ").append(proto.getQuota().getSoftLimit()); - sb.append(", VIOLATION_POLICY => ").append(proto.getQuota().getViolationPolicy()); + if (proto.getQuota().getRemove()) { + sb.append(", REMOVE => ").append(proto.getQuota().getRemove()); + } else { + sb.append(", LIMIT => ").append(proto.getQuota().getSoftLimit()); + sb.append(", VIOLATION_POLICY => ").append(proto.getQuota().getViolationPolicy()); + } return sb.toString(); } } 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 e0012a7..edf6926 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 @@ -144,5 +144,25 @@ 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 + public void testSpaceLimitSettingsForDeletes() { + final String ns = "ns1"; + final TableName tn = TableName.valueOf("tn1"); + QuotaSettings nsSettings = QuotaSettingsFactory.removeNamespaceSpaceLimit(ns); + 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()); + + 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()); + } } diff --git a/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/generated/QuotaProtos.java b/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/generated/QuotaProtos.java index 34dd16d..00aef8e 100644 --- a/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/generated/QuotaProtos.java +++ b/hbase-protocol-shaded/src/main/java/org/apache/hadoop/hbase/shaded/protobuf/generated/QuotaProtos.java @@ -4833,6 +4833,23 @@ public final class QuotaProtos { * optional .hbase.pb.SpaceViolationPolicy violation_policy = 2; */ org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceViolationPolicy getViolationPolicy(); + + /** + *
+     * When true, remove the quota.
+     * 
+ * + * optional bool remove = 3 [default = false]; + */ + boolean hasRemove(); + /** + *
+     * When true, remove the quota.
+     * 
+ * + * optional bool remove = 3 [default = false]; + */ + boolean getRemove(); } /** *
@@ -4852,6 +4869,7 @@ public final class QuotaProtos {
     private SpaceQuota() {
       softLimit_ = 0L;
       violationPolicy_ = 1;
+      remove_ = false;
     }
 
     @java.lang.Override
@@ -4898,6 +4916,11 @@ public final class QuotaProtos {
               }
               break;
             }
+            case 24: {
+              bitField0_ |= 0x00000004;
+              remove_ = input.readBool();
+              break;
+            }
           }
         }
       } catch (org.apache.hadoop.hbase.shaded.com.google.protobuf.InvalidProtocolBufferException e) {
@@ -4970,6 +4993,29 @@ public final class QuotaProtos {
       return result == null ? org.apache.hadoop.hbase.shaded.protobuf.generated.QuotaProtos.SpaceViolationPolicy.DISABLE : result;
     }
 
+    public static final int REMOVE_FIELD_NUMBER = 3;
+    private boolean remove_;
+    /**
+     * 
+     * When true, remove the quota.
+     * 
+ * + * optional bool remove = 3 [default = false]; + */ + public boolean hasRemove() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + *
+     * When true, remove the quota.
+     * 
+ * + * optional bool remove = 3 [default = false]; + */ + public boolean getRemove() { + return remove_; + } + private byte memoizedIsInitialized = -1; public final boolean isInitialized() { byte isInitialized = memoizedIsInitialized; @@ -4988,6 +5034,9 @@ public final class QuotaProtos { if (((bitField0_ & 0x00000002) == 0x00000002)) { output.writeEnum(2, violationPolicy_); } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + output.writeBool(3, remove_); + } unknownFields.writeTo(output); } @@ -5004,6 +5053,10 @@ public final class QuotaProtos { size += org.apache.hadoop.hbase.shaded.com.google.protobuf.CodedOutputStream .computeEnumSize(2, violationPolicy_); } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + size += org.apache.hadoop.hbase.shaded.com.google.protobuf.CodedOutputStream + .computeBoolSize(3, remove_); + } size += unknownFields.getSerializedSize(); memoizedSize = size; return size; @@ -5030,6 +5083,11 @@ public final class QuotaProtos { if (hasViolationPolicy()) { result = result && violationPolicy_ == other.violationPolicy_; } + result = result && (hasRemove() == other.hasRemove()); + if (hasRemove()) { + result = result && (getRemove() + == other.getRemove()); + } result = result && unknownFields.equals(other.unknownFields); return result; } @@ -5050,6 +5108,11 @@ public final class QuotaProtos { hash = (37 * hash) + VIOLATION_POLICY_FIELD_NUMBER; hash = (53 * hash) + violationPolicy_; } + if (hasRemove()) { + hash = (37 * hash) + REMOVE_FIELD_NUMBER; + hash = (53 * hash) + org.apache.hadoop.hbase.shaded.com.google.protobuf.Internal.hashBoolean( + getRemove()); + } hash = (29 * hash) + unknownFields.hashCode(); memoizedHashCode = hash; return hash; @@ -5176,6 +5239,8 @@ public final class QuotaProtos { bitField0_ = (bitField0_ & ~0x00000001); violationPolicy_ = 1; bitField0_ = (bitField0_ & ~0x00000002); + remove_ = false; + bitField0_ = (bitField0_ & ~0x00000004); return this; } @@ -5208,6 +5273,10 @@ public final class QuotaProtos { to_bitField0_ |= 0x00000002; } result.violationPolicy_ = violationPolicy_; + if (((from_bitField0_ & 0x00000004) == 0x00000004)) { + to_bitField0_ |= 0x00000004; + } + result.remove_ = remove_; result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -5256,6 +5325,9 @@ public final class QuotaProtos { if (other.hasViolationPolicy()) { setViolationPolicy(other.getViolationPolicy()); } + if (other.hasRemove()) { + setRemove(other.getRemove()); + } this.mergeUnknownFields(other.unknownFields); onChanged(); return this; @@ -5383,6 +5455,54 @@ public final class QuotaProtos { onChanged(); return this; } + + private boolean remove_ ; + /** + *
+       * When true, remove the quota.
+       * 
+ * + * optional bool remove = 3 [default = false]; + */ + public boolean hasRemove() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + *
+       * When true, remove the quota.
+       * 
+ * + * optional bool remove = 3 [default = false]; + */ + public boolean getRemove() { + return remove_; + } + /** + *
+       * When true, remove the quota.
+       * 
+ * + * optional bool remove = 3 [default = false]; + */ + public Builder setRemove(boolean value) { + bitField0_ |= 0x00000004; + remove_ = value; + onChanged(); + return this; + } + /** + *
+       * When true, remove the quota.
+       * 
+ * + * optional bool remove = 3 [default = false]; + */ + public Builder clearRemove() { + bitField0_ = (bitField0_ & ~0x00000004); + remove_ = false; + onChanged(); + return this; + } public final Builder setUnknownFields( final org.apache.hadoop.hbase.shaded.com.google.protobuf.UnknownFieldSet unknownFields) { return super.setUnknownFields(unknownFields); @@ -13019,44 +13139,44 @@ public final class QuotaProtos { "edQuota\"r\n\006Quotas\022\035\n\016bypass_globals\030\001 \001(" + "\010:\005false\022$\n\010throttle\030\002 \001(\0132\022.hbase.pb.Th" + "rottle\022#\n\005space\030\003 \001(\0132\024.hbase.pb.SpaceQu" + - "ota\"\014\n\nQuotaUsage\"Z\n\nSpaceQuota\022\022\n\nsoft_" + + "ota\"\014\n\nQuotaUsage\"q\n\nSpaceQuota\022\022\n\nsoft_" + "limit\030\001 \001(\004\0228\n\020violation_policy\030\002 \001(\0162\036." + - "hbase.pb.SpaceViolationPolicy\"8\n\021SpaceLi" + - "mitRequest\022#\n\005quota\030\001 \001(\0132\024.hbase.pb.Spa", - "ceQuota\"X\n\020SpaceQuotaStatus\022.\n\006policy\030\001 " + - "\001(\0162\036.hbase.pb.SpaceViolationPolicy\022\024\n\014i" + - "n_violation\030\002 \001(\010\"^\n\022SpaceQuotaSnapshot\022" + - "*\n\006status\030\001 \001(\0132\032.hbase.pb.SpaceQuotaSta" + - "tus\022\r\n\005usage\030\002 \001(\004\022\r\n\005limit\030\003 \001(\004\"!\n\037Get" + - "SpaceQuotaRegionSizesRequest\"\257\001\n GetSpac" + - "eQuotaRegionSizesResponse\022E\n\005sizes\030\001 \003(\013" + - "26.hbase.pb.GetSpaceQuotaRegionSizesResp" + - "onse.RegionSizes\032D\n\013RegionSizes\022\'\n\ntable" + - "_name\030\001 \001(\0132\023.hbase.pb.TableName\022\014\n\004size", - "\030\002 \001(\004\"\037\n\035GetSpaceQuotaSnapshotsRequest\"" + - "\337\001\n\036GetSpaceQuotaSnapshotsResponse\022N\n\tsn" + - "apshots\030\001 \003(\0132;.hbase.pb.GetSpaceQuotaSn" + - "apshotsResponse.TableQuotaSnapshot\032m\n\022Ta" + - "bleQuotaSnapshot\022\'\n\ntable_name\030\001 \001(\0132\023.h" + - "base.pb.TableName\022.\n\010snapshot\030\002 \001(\0132\034.hb" + - "ase.pb.SpaceQuotaSnapshot\"\"\n GetSpaceQuo" + - "taEnforcementsRequest\"\374\001\n!GetSpaceQuotaE" + - "nforcementsResponse\022\\\n\022violation_policie" + - "s\030\001 \003(\0132@.hbase.pb.GetSpaceQuotaEnforcem", - "entsResponse.TableViolationPolicy\032y\n\024Tab" + - "leViolationPolicy\022\'\n\ntable_name\030\001 \001(\0132\023." + - "hbase.pb.TableName\0228\n\020violation_policy\030\002" + - " \001(\0162\036.hbase.pb.SpaceViolationPolicy*&\n\n" + - "QuotaScope\022\013\n\007CLUSTER\020\001\022\013\n\007MACHINE\020\002*v\n\014" + - "ThrottleType\022\022\n\016REQUEST_NUMBER\020\001\022\020\n\014REQU" + - "EST_SIZE\020\002\022\020\n\014WRITE_NUMBER\020\003\022\016\n\nWRITE_SI" + - "ZE\020\004\022\017\n\013READ_NUMBER\020\005\022\r\n\tREAD_SIZE\020\006*$\n\t" + - "QuotaType\022\014\n\010THROTTLE\020\001\022\t\n\005SPACE\020\002*]\n\024Sp" + - "aceViolationPolicy\022\013\n\007DISABLE\020\001\022\031\n\025NO_WR", - "ITES_COMPACTIONS\020\002\022\r\n\tNO_WRITES\020\003\022\016\n\nNO_" + - "INSERTS\020\004BH\n1org.apache.hadoop.hbase.sha" + - "ded.protobuf.generatedB\013QuotaProtosH\001\210\001\001" + - "\240\001\001" + "hbase.pb.SpaceViolationPolicy\022\025\n\006remove\030" + + "\003 \001(\010:\005false\"8\n\021SpaceLimitRequest\022#\n\005quo", + "ta\030\001 \001(\0132\024.hbase.pb.SpaceQuota\"X\n\020SpaceQ" + + "uotaStatus\022.\n\006policy\030\001 \001(\0162\036.hbase.pb.Sp" + + "aceViolationPolicy\022\024\n\014in_violation\030\002 \001(\010" + + "\"^\n\022SpaceQuotaSnapshot\022*\n\006status\030\001 \001(\0132\032" + + ".hbase.pb.SpaceQuotaStatus\022\r\n\005usage\030\002 \001(" + + "\004\022\r\n\005limit\030\003 \001(\004\"!\n\037GetSpaceQuotaRegionS" + + "izesRequest\"\257\001\n GetSpaceQuotaRegionSizes" + + "Response\022E\n\005sizes\030\001 \003(\01326.hbase.pb.GetSp" + + "aceQuotaRegionSizesResponse.RegionSizes\032" + + "D\n\013RegionSizes\022\'\n\ntable_name\030\001 \001(\0132\023.hba", + "se.pb.TableName\022\014\n\004size\030\002 \001(\004\"\037\n\035GetSpac" + + "eQuotaSnapshotsRequest\"\337\001\n\036GetSpaceQuota" + + "SnapshotsResponse\022N\n\tsnapshots\030\001 \003(\0132;.h" + + "base.pb.GetSpaceQuotaSnapshotsResponse.T" + + "ableQuotaSnapshot\032m\n\022TableQuotaSnapshot\022" + + "\'\n\ntable_name\030\001 \001(\0132\023.hbase.pb.TableName" + + "\022.\n\010snapshot\030\002 \001(\0132\034.hbase.pb.SpaceQuota" + + "Snapshot\"\"\n GetSpaceQuotaEnforcementsReq" + + "uest\"\374\001\n!GetSpaceQuotaEnforcementsRespon" + + "se\022\\\n\022violation_policies\030\001 \003(\0132@.hbase.p", + "b.GetSpaceQuotaEnforcementsResponse.Tabl" + + "eViolationPolicy\032y\n\024TableViolationPolicy" + + "\022\'\n\ntable_name\030\001 \001(\0132\023.hbase.pb.TableNam" + + "e\0228\n\020violation_policy\030\002 \001(\0162\036.hbase.pb.S" + + "paceViolationPolicy*&\n\nQuotaScope\022\013\n\007CLU" + + "STER\020\001\022\013\n\007MACHINE\020\002*v\n\014ThrottleType\022\022\n\016R" + + "EQUEST_NUMBER\020\001\022\020\n\014REQUEST_SIZE\020\002\022\020\n\014WRI" + + "TE_NUMBER\020\003\022\016\n\nWRITE_SIZE\020\004\022\017\n\013READ_NUMB" + + "ER\020\005\022\r\n\tREAD_SIZE\020\006*$\n\tQuotaType\022\014\n\010THRO" + + "TTLE\020\001\022\t\n\005SPACE\020\002*]\n\024SpaceViolationPolic", + "y\022\013\n\007DISABLE\020\001\022\031\n\025NO_WRITES_COMPACTIONS\020" + + "\002\022\r\n\tNO_WRITES\020\003\022\016\n\nNO_INSERTS\020\004BH\n1org." + + "apache.hadoop.hbase.shaded.protobuf.gene" + + "ratedB\013QuotaProtosH\001\210\001\001\240\001\001" }; org.apache.hadoop.hbase.shaded.com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new org.apache.hadoop.hbase.shaded.com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() { @@ -13106,7 +13226,7 @@ public final class QuotaProtos { internal_static_hbase_pb_SpaceQuota_fieldAccessorTable = new org.apache.hadoop.hbase.shaded.com.google.protobuf.GeneratedMessageV3.FieldAccessorTable( internal_static_hbase_pb_SpaceQuota_descriptor, - new java.lang.String[] { "SoftLimit", "ViolationPolicy", }); + new java.lang.String[] { "SoftLimit", "ViolationPolicy", "Remove", }); internal_static_hbase_pb_SpaceLimitRequest_descriptor = getDescriptor().getMessageTypes().get(6); internal_static_hbase_pb_SpaceLimitRequest_fieldAccessorTable = new diff --git a/hbase-protocol-shaded/src/main/protobuf/Quota.proto b/hbase-protocol-shaded/src/main/protobuf/Quota.proto index 4b4369f..2d7e5f5 100644 --- a/hbase-protocol-shaded/src/main/protobuf/Quota.proto +++ b/hbase-protocol-shaded/src/main/protobuf/Quota.proto @@ -89,6 +89,7 @@ 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/java/org/apache/hadoop/hbase/protobuf/generated/QuotaProtos.java b/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/QuotaProtos.java index fe51646..96a8ab2 100644 --- a/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/QuotaProtos.java +++ b/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/QuotaProtos.java @@ -4658,6 +4658,24 @@ public final class QuotaProtos { *
*/ org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.SpaceViolationPolicy getViolationPolicy(); + + // optional bool remove = 3 [default = false]; + /** + * optional bool remove = 3 [default = false]; + * + *
+     * When true, remove the quota.
+     * 
+ */ + boolean hasRemove(); + /** + * optional bool remove = 3 [default = false]; + * + *
+     * When true, remove the quota.
+     * 
+ */ + boolean getRemove(); } /** * Protobuf type {@code hbase.pb.SpaceQuota} @@ -4730,6 +4748,11 @@ public final class QuotaProtos { } break; } + case 24: { + bitField0_ |= 0x00000004; + remove_ = input.readBool(); + break; + } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { @@ -4818,9 +4841,34 @@ public final class QuotaProtos { return violationPolicy_; } + // optional bool remove = 3 [default = false]; + public static final int REMOVE_FIELD_NUMBER = 3; + private boolean remove_; + /** + * optional bool remove = 3 [default = false]; + * + *
+     * When true, remove the quota.
+     * 
+ */ + public boolean hasRemove() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * optional bool remove = 3 [default = false]; + * + *
+     * When true, remove the quota.
+     * 
+ */ + public boolean getRemove() { + return remove_; + } + private void initFields() { softLimit_ = 0L; violationPolicy_ = org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.SpaceViolationPolicy.DISABLE; + remove_ = false; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -4840,6 +4888,9 @@ public final class QuotaProtos { if (((bitField0_ & 0x00000002) == 0x00000002)) { output.writeEnum(2, violationPolicy_.getNumber()); } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + output.writeBool(3, remove_); + } getUnknownFields().writeTo(output); } @@ -4857,6 +4908,10 @@ public final class QuotaProtos { size += com.google.protobuf.CodedOutputStream .computeEnumSize(2, violationPolicy_.getNumber()); } + if (((bitField0_ & 0x00000004) == 0x00000004)) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(3, remove_); + } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; @@ -4890,6 +4945,11 @@ public final class QuotaProtos { result = result && (getViolationPolicy() == other.getViolationPolicy()); } + result = result && (hasRemove() == other.hasRemove()); + if (hasRemove()) { + result = result && (getRemove() + == other.getRemove()); + } result = result && getUnknownFields().equals(other.getUnknownFields()); return result; @@ -4911,6 +4971,10 @@ public final class QuotaProtos { hash = (37 * hash) + VIOLATION_POLICY_FIELD_NUMBER; hash = (53 * hash) + hashEnum(getViolationPolicy()); } + if (hasRemove()) { + hash = (37 * hash) + REMOVE_FIELD_NUMBER; + hash = (53 * hash) + hashBoolean(getRemove()); + } hash = (29 * hash) + getUnknownFields().hashCode(); memoizedHashCode = hash; return hash; @@ -5028,6 +5092,8 @@ public final class QuotaProtos { bitField0_ = (bitField0_ & ~0x00000001); violationPolicy_ = org.apache.hadoop.hbase.protobuf.generated.QuotaProtos.SpaceViolationPolicy.DISABLE; bitField0_ = (bitField0_ & ~0x00000002); + remove_ = false; + bitField0_ = (bitField0_ & ~0x00000004); return this; } @@ -5064,6 +5130,10 @@ public final class QuotaProtos { to_bitField0_ |= 0x00000002; } result.violationPolicy_ = violationPolicy_; + if (((from_bitField0_ & 0x00000004) == 0x00000004)) { + to_bitField0_ |= 0x00000004; + } + result.remove_ = remove_; result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -5086,6 +5156,9 @@ public final class QuotaProtos { if (other.hasViolationPolicy()) { setViolationPolicy(other.getViolationPolicy()); } + if (other.hasRemove()) { + setRemove(other.getRemove()); + } this.mergeUnknownFields(other.getUnknownFields()); return this; } @@ -5214,6 +5287,55 @@ public final class QuotaProtos { return this; } + // optional bool remove = 3 [default = false]; + private boolean remove_ ; + /** + * optional bool remove = 3 [default = false]; + * + *
+       * When true, remove the quota.
+       * 
+ */ + public boolean hasRemove() { + return ((bitField0_ & 0x00000004) == 0x00000004); + } + /** + * optional bool remove = 3 [default = false]; + * + *
+       * When true, remove the quota.
+       * 
+ */ + public boolean getRemove() { + return remove_; + } + /** + * optional bool remove = 3 [default = false]; + * + *
+       * When true, remove the quota.
+       * 
+ */ + public Builder setRemove(boolean value) { + bitField0_ |= 0x00000004; + remove_ = value; + onChanged(); + return this; + } + /** + * optional bool remove = 3 [default = false]; + * + *
+       * When true, remove the quota.
+       * 
+ */ + public Builder clearRemove() { + bitField0_ = (bitField0_ & ~0x00000004); + remove_ = false; + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:hbase.pb.SpaceQuota) } @@ -7126,24 +7248,25 @@ public final class QuotaProtos { "edQuota\"r\n\006Quotas\022\035\n\016bypass_globals\030\001 \001(" + "\010:\005false\022$\n\010throttle\030\002 \001(\0132\022.hbase.pb.Th" + "rottle\022#\n\005space\030\003 \001(\0132\024.hbase.pb.SpaceQu" + - "ota\"\014\n\nQuotaUsage\"Z\n\nSpaceQuota\022\022\n\nsoft_" + + "ota\"\014\n\nQuotaUsage\"q\n\nSpaceQuota\022\022\n\nsoft_" + "limit\030\001 \001(\004\0228\n\020violation_policy\030\002 \001(\0162\036." + - "hbase.pb.SpaceViolationPolicy\"8\n\021SpaceLi" + - "mitRequest\022#\n\005quota\030\001 \001(\0132\024.hbase.pb.Spa", - "ceQuota\"X\n\020SpaceQuotaStatus\022.\n\006policy\030\001 " + - "\001(\0162\036.hbase.pb.SpaceViolationPolicy\022\024\n\014i" + - "n_violation\030\002 \001(\010\"^\n\022SpaceQuotaSnapshot\022" + - "*\n\006status\030\001 \001(\0132\032.hbase.pb.SpaceQuotaSta" + - "tus\022\r\n\005usage\030\002 \001(\004\022\r\n\005limit\030\003 \001(\004*&\n\nQuo" + - "taScope\022\013\n\007CLUSTER\020\001\022\013\n\007MACHINE\020\002*v\n\014Thr" + - "ottleType\022\022\n\016REQUEST_NUMBER\020\001\022\020\n\014REQUEST" + - "_SIZE\020\002\022\020\n\014WRITE_NUMBER\020\003\022\016\n\nWRITE_SIZE\020" + - "\004\022\017\n\013READ_NUMBER\020\005\022\r\n\tREAD_SIZE\020\006*$\n\tQuo" + - "taType\022\014\n\010THROTTLE\020\001\022\t\n\005SPACE\020\002*]\n\024Space", - "ViolationPolicy\022\013\n\007DISABLE\020\001\022\031\n\025NO_WRITE" + - "S_COMPACTIONS\020\002\022\r\n\tNO_WRITES\020\003\022\016\n\nNO_INS" + - "ERTS\020\004BA\n*org.apache.hadoop.hbase.protob" + - "uf.generatedB\013QuotaProtosH\001\210\001\001\240\001\001" + "hbase.pb.SpaceViolationPolicy\022\025\n\006remove\030" + + "\003 \001(\010:\005false\"8\n\021SpaceLimitRequest\022#\n\005quo", + "ta\030\001 \001(\0132\024.hbase.pb.SpaceQuota\"X\n\020SpaceQ" + + "uotaStatus\022.\n\006policy\030\001 \001(\0162\036.hbase.pb.Sp" + + "aceViolationPolicy\022\024\n\014in_violation\030\002 \001(\010" + + "\"^\n\022SpaceQuotaSnapshot\022*\n\006status\030\001 \001(\0132\032" + + ".hbase.pb.SpaceQuotaStatus\022\r\n\005usage\030\002 \001(" + + "\004\022\r\n\005limit\030\003 \001(\004*&\n\nQuotaScope\022\013\n\007CLUSTE" + + "R\020\001\022\013\n\007MACHINE\020\002*v\n\014ThrottleType\022\022\n\016REQU" + + "EST_NUMBER\020\001\022\020\n\014REQUEST_SIZE\020\002\022\020\n\014WRITE_" + + "NUMBER\020\003\022\016\n\nWRITE_SIZE\020\004\022\017\n\013READ_NUMBER\020" + + "\005\022\r\n\tREAD_SIZE\020\006*$\n\tQuotaType\022\014\n\010THROTTL", + "E\020\001\022\t\n\005SPACE\020\002*]\n\024SpaceViolationPolicy\022\013" + + "\n\007DISABLE\020\001\022\031\n\025NO_WRITES_COMPACTIONS\020\002\022\r" + + "\n\tNO_WRITES\020\003\022\016\n\nNO_INSERTS\020\004BA\n*org.apa" + + "che.hadoop.hbase.protobuf.generatedB\013Quo" + + "taProtosH\001\210\001\001\240\001\001" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -7185,7 +7308,7 @@ public final class QuotaProtos { internal_static_hbase_pb_SpaceQuota_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_hbase_pb_SpaceQuota_descriptor, - new java.lang.String[] { "SoftLimit", "ViolationPolicy", }); + new java.lang.String[] { "SoftLimit", "ViolationPolicy", "Remove", }); internal_static_hbase_pb_SpaceLimitRequest_descriptor = getDescriptor().getMessageTypes().get(6); internal_static_hbase_pb_SpaceLimitRequest_fieldAccessorTable = new diff --git a/hbase-protocol/src/main/protobuf/Quota.proto b/hbase-protocol/src/main/protobuf/Quota.proto index 02d825b..d55918a 100644 --- a/hbase-protocol/src/main/protobuf/Quota.proto +++ b/hbase-protocol/src/main/protobuf/Quota.proto @@ -89,6 +89,7 @@ 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/MasterQuotaManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/MasterQuotaManager.java index ddac6e9..a099806 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/MasterQuotaManager.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/quotas/MasterQuotaManager.java @@ -454,7 +454,14 @@ public class MasterQuotaManager implements RegionStateListener { */ void applySpaceLimit(final Quotas.Builder quotas, final SpaceLimitRequest req) { if (req.hasQuota()) { - applySpaceQuota(quotas, req.getQuota()); + SpaceQuota spaceQuota = req.getQuota(); + // If we have the remove flag, unset the space quota. + if (spaceQuota.getRemove()) { + quotas.setSpace(SpaceQuota.getDefaultInstance()); + } else { + // Otherwise, update the new quota + applySpaceQuota(quotas, req.getQuota()); + } } } diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaAdmin.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaAdmin.java index 4fc95cd..1225b2e 100644 --- a/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaAdmin.java +++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/quotas/TestQuotaAdmin.java @@ -47,6 +47,7 @@ import org.junit.experimental.categories.Category; import com.google.common.collect.Iterables; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -246,7 +247,7 @@ public class TestQuotaAdmin { } @Test - public void testSetAndGetSpaceQuota() throws Exception { + public void testSetGetRemoveSpaceQuota() throws Exception { Admin admin = TEST_UTIL.getAdmin(); final TableName tn = TableName.valueOf("table1"); final long sizeLimit = 1024L * 1024L * 1024L * 1024L * 5L; // 5TB @@ -274,10 +275,32 @@ public class TestQuotaAdmin { } finally { scanner.close(); } + + // Now, remove the quota + QuotaSettings removeQuota = QuotaSettingsFactory.removeTableSpaceLimit(tn); + admin.setQuota(removeQuota); + + // Verify that the record doesn't exist in the table + try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) { + ResultScanner rs = quotaTable.getScanner(new Scan()); + try { + assertNull("Did not expect to find a quota entry", rs.next()); + } finally { + rs.close(); + } + } + + // Verify that we can also not fetch it via the API + scanner = QuotaRetriever.open(admin.getConfiguration()); + try { + assertNull("Did not expect to find a quota entry", scanner.next()); + } finally { + scanner.close(); + } } @Test - public void testSetAndModifyQuota() throws Exception { + public void testSetModifyRemoveQuota() throws Exception { Admin admin = TEST_UTIL.getAdmin(); final TableName tn = TableName.valueOf("table1"); final long originalSizeLimit = 1024L * 1024L * 1024L * 1024L * 5L; // 5TB @@ -334,6 +357,28 @@ public class TestQuotaAdmin { } finally { quotaScanner.close(); } + + // Now, remove the quota + QuotaSettings removeQuota = QuotaSettingsFactory.removeTableSpaceLimit(tn); + admin.setQuota(removeQuota); + + // Verify that the record doesn't exist in the table + try (Table quotaTable = TEST_UTIL.getConnection().getTable(QuotaTableUtil.QUOTA_TABLE_NAME)) { + ResultScanner scanner = quotaTable.getScanner(new Scan()); + try { + assertNull("Did not expect to find a quota entry", scanner.next()); + } finally { + scanner.close(); + } + } + + // Verify that we can also not fetch it via the API + quotaScanner = QuotaRetriever.open(admin.getConfiguration()); + try { + assertNull("Did not expect to find a quota entry", quotaScanner.next()); + } finally { + quotaScanner.close(); + } } private void assertNumResults(int expected, final QuotaFilter filter) throws Exception { -- 2.10.2